1 //===- llvm/unittest/Support/ScopedPrinterTest.cpp - ScopedPrinter tests --===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/ScopedPrinter.h" 10 #include "llvm/ADT/APSInt.h" 11 #include "llvm/Support/Format.h" 12 #include "gtest/gtest.h" 13 #include <cmath> 14 #include <vector> 15 16 using namespace llvm; 17 18 TEST(JSONScopedPrinterTest, PrettyPrintCtor) { 19 auto PrintFunc = [](ScopedPrinter &W) { 20 DictScope D(W); 21 W.printString("Key", "Value"); 22 }; 23 std::string StreamBuffer; 24 raw_string_ostream OS(StreamBuffer); 25 JSONScopedPrinter PrettyPrintWriter(OS, /*PrettyPrint=*/true); 26 JSONScopedPrinter NoPrettyPrintWriter(OS, /*PrettyPrint=*/false); 27 28 const char *PrettyPrintOut = R"({ 29 "Key": "Value" 30 })"; 31 const char *NoPrettyPrintOut = R"({"Key":"Value"})"; 32 PrintFunc(PrettyPrintWriter); 33 EXPECT_EQ(PrettyPrintOut, StreamBuffer); 34 StreamBuffer.clear(); 35 PrintFunc(NoPrettyPrintWriter); 36 EXPECT_EQ(NoPrettyPrintOut, StreamBuffer); 37 } 38 39 TEST(JSONScopedPrinterTest, DelimitedScopeCtor) { 40 std::string StreamBuffer; 41 raw_string_ostream OS(StreamBuffer); 42 { 43 JSONScopedPrinter DictScopeWriter(OS, /*PrettyPrint=*/false, 44 std::make_unique<DictScope>()); 45 DictScopeWriter.printString("Label", "DictScope"); 46 } 47 EXPECT_EQ(R"({"Label":"DictScope"})", StreamBuffer); 48 StreamBuffer.clear(); 49 { 50 JSONScopedPrinter ListScopeWriter(OS, /*PrettyPrint=*/false, 51 std::make_unique<ListScope>()); 52 ListScopeWriter.printString("ListScope"); 53 } 54 EXPECT_EQ(R"(["ListScope"])", StreamBuffer); 55 StreamBuffer.clear(); 56 { 57 JSONScopedPrinter NoScopeWriter(OS, /*PrettyPrint=*/false); 58 NoScopeWriter.printString("NoScope"); 59 } 60 EXPECT_EQ(R"("NoScope")", StreamBuffer); 61 } 62 63 class ScopedPrinterTest : public ::testing::Test { 64 protected: 65 std::string StreamBuffer; 66 raw_string_ostream OS; 67 ScopedPrinter Writer; 68 JSONScopedPrinter JSONWriter; 69 70 bool HasPrintedToJSON; 71 72 ScopedPrinterTest() 73 : OS(StreamBuffer), Writer(OS), JSONWriter(OS, /*PrettyPrint=*/true), 74 HasPrintedToJSON(false) {} 75 76 using PrintFunc = function_ref<void(ScopedPrinter &)>; 77 78 void verifyScopedPrinter(StringRef Expected, PrintFunc Func) { 79 Func(Writer); 80 Writer.flush(); 81 EXPECT_EQ(Expected.str(), StreamBuffer); 82 StreamBuffer.clear(); 83 } 84 85 void verifyJSONScopedPrinter(StringRef Expected, PrintFunc Func) { 86 { 87 DictScope D(JSONWriter); 88 Func(JSONWriter); 89 } 90 JSONWriter.flush(); 91 EXPECT_EQ(Expected.str(), StreamBuffer); 92 StreamBuffer.clear(); 93 HasPrintedToJSON = true; 94 } 95 96 void verifyAll(StringRef ExpectedOut, StringRef JSONExpectedOut, 97 PrintFunc Func) { 98 verifyScopedPrinter(ExpectedOut, Func); 99 verifyJSONScopedPrinter(JSONExpectedOut, Func); 100 } 101 102 void TearDown() { 103 // JSONScopedPrinter fails an assert if nothing's been printed. 104 if (!HasPrintedToJSON) 105 JSONWriter.printString(""); 106 } 107 }; 108 109 TEST_F(ScopedPrinterTest, GetKind) { 110 EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::Base, Writer.getKind()); 111 EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::JSON, JSONWriter.getKind()); 112 } 113 114 TEST_F(ScopedPrinterTest, ClassOf) { 115 EXPECT_TRUE(ScopedPrinter::classof(&Writer)); 116 EXPECT_TRUE(JSONScopedPrinter::classof(&JSONWriter)); 117 EXPECT_FALSE(ScopedPrinter::classof(&JSONWriter)); 118 EXPECT_FALSE(JSONScopedPrinter::classof(&Writer)); 119 } 120 121 TEST_F(ScopedPrinterTest, Indent) { 122 auto PrintFunc = [](ScopedPrinter &W) { 123 W.printString("|"); 124 W.indent(); 125 W.printString("|"); 126 W.indent(2); 127 W.printString("|"); 128 }; 129 130 const char *ExpectedOut = R"(| 131 | 132 | 133 )"; 134 verifyScopedPrinter(ExpectedOut, PrintFunc); 135 } 136 137 TEST_F(ScopedPrinterTest, Unindent) { 138 auto PrintFunc = [](ScopedPrinter &W) { 139 W.indent(3); 140 W.printString("|"); 141 W.unindent(2); 142 W.printString("|"); 143 W.unindent(); 144 W.printString("|"); 145 W.unindent(); 146 W.printString("|"); 147 }; 148 149 const char *ExpectedOut = R"( | 150 | 151 | 152 | 153 )"; 154 verifyScopedPrinter(ExpectedOut, PrintFunc); 155 } 156 157 TEST_F(ScopedPrinterTest, ResetIndent) { 158 auto PrintFunc = [](ScopedPrinter &W) { 159 W.indent(4); 160 W.printString("|"); 161 W.resetIndent(); 162 W.printString("|"); 163 }; 164 165 const char *ExpectedOut = R"( | 166 | 167 )"; 168 verifyScopedPrinter(ExpectedOut, PrintFunc); 169 } 170 171 TEST_F(ScopedPrinterTest, PrintIndent) { 172 auto PrintFunc = [](ScopedPrinter &W) { 173 W.printIndent(); 174 W.printString("|"); 175 W.indent(); 176 W.printIndent(); 177 W.printString("|"); 178 }; 179 180 const char *ExpectedOut = R"(| 181 | 182 )"; 183 verifyScopedPrinter(ExpectedOut, PrintFunc); 184 } 185 186 TEST_F(ScopedPrinterTest, GetIndentLevel) { 187 EXPECT_EQ(Writer.getIndentLevel(), 0); 188 Writer.indent(); 189 EXPECT_EQ(Writer.getIndentLevel(), 1); 190 Writer.indent(); 191 EXPECT_EQ(Writer.getIndentLevel(), 2); 192 Writer.unindent(); 193 EXPECT_EQ(Writer.getIndentLevel(), 1); 194 Writer.indent(); 195 Writer.resetIndent(); 196 EXPECT_EQ(Writer.getIndentLevel(), 0); 197 Writer.unindent(); 198 EXPECT_EQ(Writer.getIndentLevel(), 0); 199 Writer.indent(); 200 EXPECT_EQ(Writer.getIndentLevel(), 1); 201 } 202 203 TEST_F(ScopedPrinterTest, SetPrefix) { 204 auto PrintFunc = [](ScopedPrinter &W) { 205 W.setPrefix("Prefix1"); 206 W.indent(); 207 W.printIndent(); 208 W.printString("|"); 209 W.unindent(); 210 W.printIndent(); 211 W.printString("|"); 212 W.setPrefix("Prefix2"); 213 W.printIndent(); 214 W.printString("|"); 215 }; 216 217 const char *ExpectedOut = R"(Prefix1 Prefix1 | 218 Prefix1Prefix1| 219 Prefix2Prefix2| 220 )"; 221 verifyScopedPrinter(ExpectedOut, PrintFunc); 222 } 223 224 TEST_F(ScopedPrinterTest, PrintEnum) { 225 auto PrintFunc = [](ScopedPrinter &W) { 226 const EnumEntry<int> EnumList[] = {{"Name1", "AltName1", 1}, 227 {"Name2", "AltName2", 2}, 228 {"Name3", "AltName3", 3}, 229 {"Name4", "AltName4", 2}}; 230 EnumEntry<int> OtherEnum{"Name5", "AltName5", 5}; 231 W.printEnum("Exists", EnumList[1].Value, ArrayRef(EnumList)); 232 W.printEnum("DoesNotExist", OtherEnum.Value, ArrayRef(EnumList)); 233 }; 234 235 const char *ExpectedOut = R"(Exists: Name2 (0x2) 236 DoesNotExist: 0x5 237 )"; 238 239 const char *JSONExpectedOut = R"({ 240 "Exists": { 241 "Name": "Name2", 242 "Value": 2 243 }, 244 "DoesNotExist": 5 245 })"; 246 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 247 } 248 249 TEST_F(ScopedPrinterTest, PrintFlag) { 250 auto PrintFunc = [](ScopedPrinter &W) { 251 const EnumEntry<uint16_t> SingleBitFlags[] = { 252 {"Name0", "AltName0", 0}, 253 {"Name1", "AltName1", 1}, 254 {"Name2", "AltName2", 1 << 1}, 255 {"Name3", "AltName3", 1 << 2}}; 256 const EnumEntry<uint16_t> UnsortedFlags[] = { 257 {"C", "c", 1}, {"B", "b", 1 << 1}, {"A", "a", 1 << 2}}; 258 const EnumEntry<uint16_t> EnumFlags[] = { 259 {"FirstByte1", "First1", 0x1u}, {"FirstByte2", "First2", 0x2u}, 260 {"FirstByte3", "First3", 0x3u}, {"SecondByte1", "Second1", 0x10u}, 261 {"SecondByte2", "Second2", 0x20u}, {"SecondByte3", "Second3", 0x30u}, 262 {"ThirdByte1", "Third1", 0x100u}, {"ThirdByte2", "Third2", 0x200u}, 263 {"ThirdByte3", "Third3", 0x300u}}; 264 W.printFlags("ZeroFlag", 0, ArrayRef(SingleBitFlags)); 265 W.printFlags("NoFlag", 1 << 3, ArrayRef(SingleBitFlags)); 266 W.printFlags("Flag1", SingleBitFlags[1].Value, ArrayRef(SingleBitFlags)); 267 W.printFlags("Flag1&3", (1 << 2) + 1, ArrayRef(SingleBitFlags)); 268 269 W.printFlags("ZeroFlagRaw", 0); 270 W.printFlags("NoFlagRaw", 1 << 3); 271 W.printFlags("Flag1Raw", SingleBitFlags[1].Value); 272 W.printFlags("Flag1&3Raw", (1 << 2) + 1); 273 274 W.printFlags("FlagSorted", (1 << 2) + (1 << 1) + 1, 275 ArrayRef(UnsortedFlags)); 276 277 uint16_t NoBitMask = 0; 278 uint16_t FirstByteMask = 0xFu; 279 uint16_t SecondByteMask = 0xF0u; 280 uint16_t ThirdByteMask = 0xF00u; 281 W.printFlags("NoBitMask", 0xFFFu, ArrayRef(EnumFlags), NoBitMask); 282 W.printFlags("FirstByteMask", 0x3u, ArrayRef(EnumFlags), FirstByteMask); 283 W.printFlags("SecondByteMask", 0x30u, ArrayRef(EnumFlags), SecondByteMask); 284 W.printFlags("ValueOutsideMask", 0x1u, ArrayRef(EnumFlags), SecondByteMask); 285 W.printFlags("FirstSecondByteMask", 0xFFu, ArrayRef(EnumFlags), 286 FirstByteMask, SecondByteMask); 287 W.printFlags("FirstSecondThirdByteMask", 0x333u, ArrayRef(EnumFlags), 288 FirstByteMask, SecondByteMask, ThirdByteMask); 289 }; 290 291 const char *ExpectedOut = R"(ZeroFlag [ (0x0) 292 ] 293 NoFlag [ (0x8) 294 ] 295 Flag1 [ (0x1) 296 Name1 (0x1) 297 ] 298 Flag1&3 [ (0x5) 299 Name1 (0x1) 300 Name3 (0x4) 301 ] 302 ZeroFlagRaw [ (0x0) 303 ] 304 NoFlagRaw [ (0x8) 305 0x8 306 ] 307 Flag1Raw [ (0x1) 308 0x1 309 ] 310 Flag1&3Raw [ (0x5) 311 0x1 312 0x4 313 ] 314 FlagSorted [ (0x7) 315 A (0x4) 316 B (0x2) 317 C (0x1) 318 ] 319 NoBitMask [ (0xFFF) 320 FirstByte1 (0x1) 321 FirstByte2 (0x2) 322 FirstByte3 (0x3) 323 SecondByte1 (0x10) 324 SecondByte2 (0x20) 325 SecondByte3 (0x30) 326 ThirdByte1 (0x100) 327 ThirdByte2 (0x200) 328 ThirdByte3 (0x300) 329 ] 330 FirstByteMask [ (0x3) 331 FirstByte3 (0x3) 332 ] 333 SecondByteMask [ (0x30) 334 SecondByte3 (0x30) 335 ] 336 ValueOutsideMask [ (0x1) 337 FirstByte1 (0x1) 338 ] 339 FirstSecondByteMask [ (0xFF) 340 ] 341 FirstSecondThirdByteMask [ (0x333) 342 FirstByte3 (0x3) 343 SecondByte3 (0x30) 344 ThirdByte3 (0x300) 345 ] 346 )"; 347 348 const char *JSONExpectedOut = R"({ 349 "ZeroFlag": { 350 "Value": 0, 351 "Flags": [] 352 }, 353 "NoFlag": { 354 "Value": 8, 355 "Flags": [] 356 }, 357 "Flag1": { 358 "Value": 1, 359 "Flags": [ 360 { 361 "Name": "Name1", 362 "Value": 1 363 } 364 ] 365 }, 366 "Flag1&3": { 367 "Value": 5, 368 "Flags": [ 369 { 370 "Name": "Name1", 371 "Value": 1 372 }, 373 { 374 "Name": "Name3", 375 "Value": 4 376 } 377 ] 378 }, 379 "ZeroFlagRaw": { 380 "Value": 0, 381 "Flags": [] 382 }, 383 "NoFlagRaw": { 384 "Value": 8, 385 "Flags": [ 386 8 387 ] 388 }, 389 "Flag1Raw": { 390 "Value": 1, 391 "Flags": [ 392 1 393 ] 394 }, 395 "Flag1&3Raw": { 396 "Value": 5, 397 "Flags": [ 398 1, 399 4 400 ] 401 }, 402 "FlagSorted": { 403 "Value": 7, 404 "Flags": [ 405 { 406 "Name": "A", 407 "Value": 4 408 }, 409 { 410 "Name": "B", 411 "Value": 2 412 }, 413 { 414 "Name": "C", 415 "Value": 1 416 } 417 ] 418 }, 419 "NoBitMask": { 420 "Value": 4095, 421 "Flags": [ 422 { 423 "Name": "FirstByte1", 424 "Value": 1 425 }, 426 { 427 "Name": "FirstByte2", 428 "Value": 2 429 }, 430 { 431 "Name": "FirstByte3", 432 "Value": 3 433 }, 434 { 435 "Name": "SecondByte1", 436 "Value": 16 437 }, 438 { 439 "Name": "SecondByte2", 440 "Value": 32 441 }, 442 { 443 "Name": "SecondByte3", 444 "Value": 48 445 }, 446 { 447 "Name": "ThirdByte1", 448 "Value": 256 449 }, 450 { 451 "Name": "ThirdByte2", 452 "Value": 512 453 }, 454 { 455 "Name": "ThirdByte3", 456 "Value": 768 457 } 458 ] 459 }, 460 "FirstByteMask": { 461 "Value": 3, 462 "Flags": [ 463 { 464 "Name": "FirstByte3", 465 "Value": 3 466 } 467 ] 468 }, 469 "SecondByteMask": { 470 "Value": 48, 471 "Flags": [ 472 { 473 "Name": "SecondByte3", 474 "Value": 48 475 } 476 ] 477 }, 478 "ValueOutsideMask": { 479 "Value": 1, 480 "Flags": [ 481 { 482 "Name": "FirstByte1", 483 "Value": 1 484 } 485 ] 486 }, 487 "FirstSecondByteMask": { 488 "Value": 255, 489 "Flags": [] 490 }, 491 "FirstSecondThirdByteMask": { 492 "Value": 819, 493 "Flags": [ 494 { 495 "Name": "FirstByte3", 496 "Value": 3 497 }, 498 { 499 "Name": "SecondByte3", 500 "Value": 48 501 }, 502 { 503 "Name": "ThirdByte3", 504 "Value": 768 505 } 506 ] 507 } 508 })"; 509 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 510 } 511 512 // Format floats using the same format string as PrintNumber, so we can check 513 // the output on all platforms. 514 template <typename T, 515 std::enable_if_t<std::is_floating_point_v<T>, bool> = true> 516 std::string formatFloatString(T Val) { 517 std::string Ret; 518 raw_string_ostream OS(Ret); 519 OS << format("%5.1f", Val); 520 return Ret; 521 } 522 523 // Format floats using the same format string used in JSON, so we can check the 524 // output on all platforms. 525 template <typename T, 526 std::enable_if_t<std::is_floating_point_v<T>, bool> = true> 527 std::string formatJsonFloatString(T Val) { 528 std::string Ret; 529 raw_string_ostream OS(Ret); 530 OS << format("%.*g", std::numeric_limits<double>::max_digits10, Val); 531 return Ret; 532 } 533 534 TEST_F(ScopedPrinterTest, PrintNumber) { 535 constexpr float MaxFloat = std::numeric_limits<float>::max(); 536 constexpr float MinFloat = std::numeric_limits<float>::min(); 537 constexpr float InfFloat = std::numeric_limits<float>::infinity(); 538 const float NaNFloat = std::nanf("1"); 539 constexpr double MaxDouble = std::numeric_limits<double>::max(); 540 constexpr double MinDouble = std::numeric_limits<double>::min(); 541 constexpr double InfDouble = std::numeric_limits<double>::infinity(); 542 const double NaNDouble = std::nan("1"); 543 544 auto PrintFunc = [&](ScopedPrinter &W) { 545 uint64_t Unsigned64Max = std::numeric_limits<uint64_t>::max(); 546 uint64_t Unsigned64Min = std::numeric_limits<uint64_t>::min(); 547 W.printNumber("uint64_t-max", Unsigned64Max); 548 W.printNumber("uint64_t-min", Unsigned64Min); 549 550 uint32_t Unsigned32Max = std::numeric_limits<uint32_t>::max(); 551 uint32_t Unsigned32Min = std::numeric_limits<uint32_t>::min(); 552 W.printNumber("uint32_t-max", Unsigned32Max); 553 W.printNumber("uint32_t-min", Unsigned32Min); 554 555 uint16_t Unsigned16Max = std::numeric_limits<uint16_t>::max(); 556 uint16_t Unsigned16Min = std::numeric_limits<uint16_t>::min(); 557 W.printNumber("uint16_t-max", Unsigned16Max); 558 W.printNumber("uint16_t-min", Unsigned16Min); 559 560 uint8_t Unsigned8Max = std::numeric_limits<uint8_t>::max(); 561 uint8_t Unsigned8Min = std::numeric_limits<uint8_t>::min(); 562 W.printNumber("uint8_t-max", Unsigned8Max); 563 W.printNumber("uint8_t-min", Unsigned8Min); 564 565 int64_t Signed64Max = std::numeric_limits<int64_t>::max(); 566 int64_t Signed64Min = std::numeric_limits<int64_t>::min(); 567 W.printNumber("int64_t-max", Signed64Max); 568 W.printNumber("int64_t-min", Signed64Min); 569 570 int32_t Signed32Max = std::numeric_limits<int32_t>::max(); 571 int32_t Signed32Min = std::numeric_limits<int32_t>::min(); 572 W.printNumber("int32_t-max", Signed32Max); 573 W.printNumber("int32_t-min", Signed32Min); 574 575 int16_t Signed16Max = std::numeric_limits<int16_t>::max(); 576 int16_t Signed16Min = std::numeric_limits<int16_t>::min(); 577 W.printNumber("int16_t-max", Signed16Max); 578 W.printNumber("int16_t-min", Signed16Min); 579 580 int8_t Signed8Max = std::numeric_limits<int8_t>::max(); 581 int8_t Signed8Min = std::numeric_limits<int8_t>::min(); 582 W.printNumber("int8_t-max", Signed8Max); 583 W.printNumber("int8_t-min", Signed8Min); 584 585 APSInt LargeNum("9999999999999999999999"); 586 W.printNumber("apsint", LargeNum); 587 588 W.printNumber("label", "value", 0); 589 590 W.printNumber("float-max", MaxFloat); 591 W.printNumber("float-min", MinFloat); 592 W.printNumber("float-inf", InfFloat); 593 W.printNumber("float-nan", NaNFloat); 594 W.printNumber("float-42.0", 42.0f); 595 W.printNumber("float-42.5625", 42.5625f); 596 597 W.printNumber("double-max", MaxDouble); 598 W.printNumber("double-min", MinDouble); 599 W.printNumber("double-inf", InfDouble); 600 W.printNumber("double-nan", NaNDouble); 601 W.printNumber("double-42.0", 42.0); 602 W.printNumber("double-42.5625", 42.5625); 603 }; 604 605 std::string ExpectedOut = Twine( 606 R"(uint64_t-max: 18446744073709551615 607 uint64_t-min: 0 608 uint32_t-max: 4294967295 609 uint32_t-min: 0 610 uint16_t-max: 65535 611 uint16_t-min: 0 612 uint8_t-max: 255 613 uint8_t-min: 0 614 int64_t-max: 9223372036854775807 615 int64_t-min: -9223372036854775808 616 int32_t-max: 2147483647 617 int32_t-min: -2147483648 618 int16_t-max: 32767 619 int16_t-min: -32768 620 int8_t-max: 127 621 int8_t-min: -128 622 apsint: 9999999999999999999999 623 label: value (0) 624 float-max: )" + formatFloatString(MaxFloat) + 625 R"( 626 float-min: 0.0 627 float-inf: )" + formatFloatString(InfFloat) + 628 R"( 629 float-nan: )" + formatFloatString(NaNFloat) + 630 R"( 631 float-42.0: 42.0 632 float-42.5625: 42.6 633 double-max: )" + formatFloatString(MaxDouble) + 634 R"( 635 double-min: 0.0 636 double-inf: )" + formatFloatString(InfDouble) + 637 R"( 638 double-nan: )" + formatFloatString(NaNDouble) + 639 R"( 640 double-42.0: 42.0 641 double-42.5625: 42.6 642 )") 643 .str(); 644 645 std::string JSONExpectedOut = Twine(R"({ 646 "uint64_t-max": 18446744073709551615, 647 "uint64_t-min": 0, 648 "uint32_t-max": 4294967295, 649 "uint32_t-min": 0, 650 "uint16_t-max": 65535, 651 "uint16_t-min": 0, 652 "uint8_t-max": 255, 653 "uint8_t-min": 0, 654 "int64_t-max": 9223372036854775807, 655 "int64_t-min": -9223372036854775808, 656 "int32_t-max": 2147483647, 657 "int32_t-min": -2147483648, 658 "int16_t-max": 32767, 659 "int16_t-min": -32768, 660 "int8_t-max": 127, 661 "int8_t-min": -128, 662 "apsint": 9999999999999999999999, 663 "label": { 664 "Name": "value", 665 "Value": 0 666 }, 667 "float-max": 3.4028234663852886e+38, 668 "float-min": 1.1754943508222875e-38, 669 "float-inf": )" + formatJsonFloatString(InfFloat) + 670 R"(, 671 "float-nan": )" + formatJsonFloatString(NaNFloat) + 672 R"(, 673 "float-42.0": 42, 674 "float-42.5625": 42.5625, 675 "double-max": 1.7976931348623157e+308, 676 "double-min": 2.2250738585072014e-308, 677 "double-inf": )" + formatJsonFloatString(InfDouble) + 678 R"(, 679 "double-nan": )" + formatJsonFloatString(NaNDouble) + 680 R"(, 681 "double-42.0": 42, 682 "double-42.5625": 42.5625 683 })") 684 .str(); 685 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 686 } 687 688 TEST_F(ScopedPrinterTest, PrintBoolean) { 689 auto PrintFunc = [](ScopedPrinter &W) { 690 W.printBoolean("True", true); 691 W.printBoolean("False", false); 692 }; 693 694 const char *ExpectedOut = R"(True: Yes 695 False: No 696 )"; 697 698 const char *JSONExpectedOut = R"({ 699 "True": true, 700 "False": false 701 })"; 702 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 703 } 704 705 TEST_F(ScopedPrinterTest, PrintVersion) { 706 auto PrintFunc = [](ScopedPrinter &W) { 707 W.printVersion("Version", "123", "456", "789"); 708 }; 709 const char *ExpectedOut = R"(Version: 123.456.789 710 )"; 711 verifyScopedPrinter(ExpectedOut, PrintFunc); 712 } 713 714 TEST_F(ScopedPrinterTest, PrintList) { 715 auto PrintFunc = [](ScopedPrinter &W) { 716 const std::vector<uint64_t> EmptyList; 717 const std::vector<std::string> StringList = {"foo", "bar", "baz"}; 718 const bool BoolList[] = {true, false}; 719 const std::vector<uint64_t> Unsigned64List = { 720 std::numeric_limits<uint64_t>::max(), 721 std::numeric_limits<uint64_t>::min()}; 722 const std::vector<uint32_t> Unsigned32List = { 723 std::numeric_limits<uint32_t>::max(), 724 std::numeric_limits<uint32_t>::min()}; 725 const std::vector<uint16_t> Unsigned16List = { 726 std::numeric_limits<uint16_t>::max(), 727 std::numeric_limits<uint16_t>::min()}; 728 const std::vector<uint8_t> Unsigned8List = { 729 std::numeric_limits<uint8_t>::max(), 730 std::numeric_limits<uint8_t>::min()}; 731 const std::vector<int64_t> Signed64List = { 732 std::numeric_limits<int64_t>::max(), 733 std::numeric_limits<int64_t>::min()}; 734 const std::vector<int32_t> Signed32List = { 735 std::numeric_limits<int32_t>::max(), 736 std::numeric_limits<int32_t>::min()}; 737 const std::vector<int16_t> Signed16List = { 738 std::numeric_limits<int16_t>::max(), 739 std::numeric_limits<int16_t>::min()}; 740 const std::vector<int8_t> Signed8List = { 741 std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min()}; 742 const std::vector<APSInt> APSIntList = {APSInt("9999999999999999999999"), 743 APSInt("-9999999999999999999999")}; 744 W.printList("EmptyList", EmptyList); 745 W.printList("StringList", StringList); 746 W.printList("BoolList", ArrayRef(BoolList)); 747 W.printList("uint64List", Unsigned64List); 748 W.printList("uint32List", Unsigned32List); 749 W.printList("uint16List", Unsigned16List); 750 W.printList("uint8List", Unsigned8List); 751 W.printList("int64List", Signed64List); 752 W.printList("int32List", Signed32List); 753 W.printList("int16List", Signed16List); 754 W.printList("int8List", Signed8List); 755 W.printList("APSIntList", APSIntList); 756 }; 757 758 const char *ExpectedOut = R"(EmptyList: [] 759 StringList: [foo, bar, baz] 760 BoolList: [1, 0] 761 uint64List: [18446744073709551615, 0] 762 uint32List: [4294967295, 0] 763 uint16List: [65535, 0] 764 uint8List: [255, 0] 765 int64List: [9223372036854775807, -9223372036854775808] 766 int32List: [2147483647, -2147483648] 767 int16List: [32767, -32768] 768 int8List: [127, -128] 769 APSIntList: [9999999999999999999999, -9999999999999999999999] 770 )"; 771 772 const char *JSONExpectedOut = R"({ 773 "EmptyList": [], 774 "StringList": [ 775 "foo", 776 "bar", 777 "baz" 778 ], 779 "BoolList": [ 780 true, 781 false 782 ], 783 "uint64List": [ 784 18446744073709551615, 785 0 786 ], 787 "uint32List": [ 788 4294967295, 789 0 790 ], 791 "uint16List": [ 792 65535, 793 0 794 ], 795 "uint8List": [ 796 255, 797 0 798 ], 799 "int64List": [ 800 9223372036854775807, 801 -9223372036854775808 802 ], 803 "int32List": [ 804 2147483647, 805 -2147483648 806 ], 807 "int16List": [ 808 32767, 809 -32768 810 ], 811 "int8List": [ 812 127, 813 -128 814 ], 815 "APSIntList": [ 816 9999999999999999999999, 817 -9999999999999999999999 818 ] 819 })"; 820 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 821 } 822 823 TEST_F(ScopedPrinterTest, PrintListPrinter) { 824 auto PrintFunc = [](ScopedPrinter &W) { 825 const std::string StringList[] = {"a", "ab", "abc"}; 826 W.printList("StringSizeList", StringList, 827 [](raw_ostream &OS, StringRef Item) { OS << Item.size(); }); 828 }; 829 830 const char *ExpectedOut = R"(StringSizeList: [1, 2, 3] 831 )"; 832 verifyScopedPrinter(ExpectedOut, PrintFunc); 833 } 834 835 TEST_F(ScopedPrinterTest, PrintHex) { 836 auto PrintFunc = [](ScopedPrinter &W) { 837 W.printHex("HexNumber", 0x10); 838 W.printHex("HexLabel", "Name", 0x10); 839 }; 840 841 const char *ExpectedOut = R"(HexNumber: 0x10 842 HexLabel: Name (0x10) 843 )"; 844 845 const char *JSONExpectedOut = R"({ 846 "HexNumber": 16, 847 "HexLabel": { 848 "Name": "Name", 849 "Value": 16 850 } 851 })"; 852 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 853 } 854 855 TEST_F(ScopedPrinterTest, PrintHexList) { 856 auto PrintFunc = [](ScopedPrinter &W) { 857 const uint64_t HexList[] = {0x1, 0x10, 0x100}; 858 W.printHexList("HexList", HexList); 859 }; 860 const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100] 861 )"; 862 863 const char *JSONExpectedOut = R"({ 864 "HexList": [ 865 1, 866 16, 867 256 868 ] 869 })"; 870 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 871 } 872 873 TEST_F(ScopedPrinterTest, PrintSymbolOffset) { 874 auto PrintFunc = [](ScopedPrinter &W) { 875 W.printSymbolOffset("SymbolOffset", "SymbolName", 0x10); 876 W.printSymbolOffset("NoSymbolOffset", "SymbolName", 0); 877 }; 878 const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10 879 NoSymbolOffset: SymbolName+0x0 880 )"; 881 882 const char *JSONExpectedOut = R"({ 883 "SymbolOffset": { 884 "SymName": "SymbolName", 885 "Offset": 16 886 }, 887 "NoSymbolOffset": { 888 "SymName": "SymbolName", 889 "Offset": 0 890 } 891 })"; 892 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 893 } 894 895 TEST_F(ScopedPrinterTest, PrintString) { 896 auto PrintFunc = [](ScopedPrinter &W) { 897 const StringRef StringRefValue("Value"); 898 const std::string StringValue = "Value"; 899 const char *CharArrayValue = "Value"; 900 W.printString("StringRef", StringRefValue); 901 W.printString("String", StringValue); 902 W.printString("CharArray", CharArrayValue); 903 ListScope L(W, "StringList"); 904 W.printString(StringRefValue); 905 }; 906 907 const char *ExpectedOut = R"(StringRef: Value 908 String: Value 909 CharArray: Value 910 StringList [ 911 Value 912 ] 913 )"; 914 915 const char *JSONExpectedOut = R"({ 916 "StringRef": "Value", 917 "String": "Value", 918 "CharArray": "Value", 919 "StringList": [ 920 "Value" 921 ] 922 })"; 923 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 924 } 925 926 TEST_F(ScopedPrinterTest, PrintBinary) { 927 auto PrintFunc = [](ScopedPrinter &W) { 928 std::vector<uint8_t> IntArray = {70, 111, 111, 66, 97, 114}; 929 std::vector<char> CharArray = {'F', 'o', 'o', 'B', 'a', 'r'}; 930 std::vector<uint8_t> InvalidChars = {255, 255}; 931 W.printBinary("Binary1", "FooBar", IntArray); 932 W.printBinary("Binary2", "FooBar", CharArray); 933 W.printBinary("Binary3", IntArray); 934 W.printBinary("Binary4", CharArray); 935 W.printBinary("Binary5", StringRef("FooBar")); 936 W.printBinary("Binary6", StringRef("Multiple Line FooBar")); 937 W.printBinaryBlock("Binary7", IntArray, 20); 938 W.printBinaryBlock("Binary8", IntArray); 939 W.printBinaryBlock("Binary9", "FooBar"); 940 W.printBinaryBlock("Binary10", "Multiple Line FooBar"); 941 W.printBinaryBlock("Binary11", InvalidChars); 942 }; 943 944 const char *ExpectedOut = R"(Binary1: FooBar (46 6F 6F 42 61 72) 945 Binary2: FooBar (46 6F 6F 42 61 72) 946 Binary3: (46 6F 6F 42 61 72) 947 Binary4: (46 6F 6F 42 61 72) 948 Binary5: (46 6F 6F 42 61 72) 949 Binary6 ( 950 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo| 951 0010: 6F426172 |oBar| 952 ) 953 Binary7 ( 954 0014: 466F6F42 6172 |FooBar| 955 ) 956 Binary8 ( 957 0000: 466F6F42 6172 |FooBar| 958 ) 959 Binary9 ( 960 0000: 466F6F42 6172 |FooBar| 961 ) 962 Binary10 ( 963 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo| 964 0010: 6F426172 |oBar| 965 ) 966 Binary11 ( 967 0000: FFFF |..| 968 ) 969 )"; 970 971 const char *JSONExpectedOut = R"({ 972 "Binary1": { 973 "Value": "FooBar", 974 "Offset": 0, 975 "Bytes": [ 976 70, 977 111, 978 111, 979 66, 980 97, 981 114 982 ] 983 }, 984 "Binary2": { 985 "Value": "FooBar", 986 "Offset": 0, 987 "Bytes": [ 988 70, 989 111, 990 111, 991 66, 992 97, 993 114 994 ] 995 }, 996 "Binary3": { 997 "Offset": 0, 998 "Bytes": [ 999 70, 1000 111, 1001 111, 1002 66, 1003 97, 1004 114 1005 ] 1006 }, 1007 "Binary4": { 1008 "Offset": 0, 1009 "Bytes": [ 1010 70, 1011 111, 1012 111, 1013 66, 1014 97, 1015 114 1016 ] 1017 }, 1018 "Binary5": { 1019 "Offset": 0, 1020 "Bytes": [ 1021 70, 1022 111, 1023 111, 1024 66, 1025 97, 1026 114 1027 ] 1028 }, 1029 "Binary6": { 1030 "Offset": 0, 1031 "Bytes": [ 1032 77, 1033 117, 1034 108, 1035 116, 1036 105, 1037 112, 1038 108, 1039 101, 1040 32, 1041 76, 1042 105, 1043 110, 1044 101, 1045 32, 1046 70, 1047 111, 1048 111, 1049 66, 1050 97, 1051 114 1052 ] 1053 }, 1054 "Binary7": { 1055 "Offset": 20, 1056 "Bytes": [ 1057 70, 1058 111, 1059 111, 1060 66, 1061 97, 1062 114 1063 ] 1064 }, 1065 "Binary8": { 1066 "Offset": 0, 1067 "Bytes": [ 1068 70, 1069 111, 1070 111, 1071 66, 1072 97, 1073 114 1074 ] 1075 }, 1076 "Binary9": { 1077 "Offset": 0, 1078 "Bytes": [ 1079 70, 1080 111, 1081 111, 1082 66, 1083 97, 1084 114 1085 ] 1086 }, 1087 "Binary10": { 1088 "Offset": 0, 1089 "Bytes": [ 1090 77, 1091 117, 1092 108, 1093 116, 1094 105, 1095 112, 1096 108, 1097 101, 1098 32, 1099 76, 1100 105, 1101 110, 1102 101, 1103 32, 1104 70, 1105 111, 1106 111, 1107 66, 1108 97, 1109 114 1110 ] 1111 }, 1112 "Binary11": { 1113 "Offset": 0, 1114 "Bytes": [ 1115 255, 1116 255 1117 ] 1118 } 1119 })"; 1120 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 1121 } 1122 1123 TEST_F(ScopedPrinterTest, PrintObject) { 1124 auto PrintFunc = [](ScopedPrinter &W) { W.printObject("Object", "Value"); }; 1125 1126 const char *ExpectedOut = R"(Object: Value 1127 )"; 1128 1129 const char *JSONExpectedOut = R"({ 1130 "Object": "Value" 1131 })"; 1132 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 1133 } 1134 1135 TEST_F(ScopedPrinterTest, StartLine) { 1136 auto PrintFunc = [](ScopedPrinter &W) { 1137 W.startLine() << "|"; 1138 W.indent(2); 1139 W.startLine() << "|"; 1140 W.unindent(); 1141 W.startLine() << "|"; 1142 }; 1143 1144 const char *ExpectedOut = "| | |"; 1145 verifyScopedPrinter(ExpectedOut, PrintFunc); 1146 } 1147 1148 TEST_F(ScopedPrinterTest, GetOStream) { 1149 auto PrintFunc = [](ScopedPrinter &W) { W.getOStream() << "Test"; }; 1150 1151 const char *ExpectedOut = "Test"; 1152 verifyScopedPrinter(ExpectedOut, PrintFunc); 1153 } 1154 1155 TEST_F(ScopedPrinterTest, PrintScope) { 1156 auto PrintFunc = [](ScopedPrinter &W) { 1157 { 1158 DictScope O(W, "Object"); 1159 { DictScope OO(W, "ObjectInObject"); } 1160 { ListScope LO(W, "ListInObject"); } 1161 } 1162 { 1163 ListScope L(W, "List"); 1164 { DictScope OL(W, "ObjectInList"); } 1165 { ListScope LL(W, "ListInList"); } 1166 } 1167 }; 1168 1169 const char *ExpectedOut = R"(Object { 1170 ObjectInObject { 1171 } 1172 ListInObject [ 1173 ] 1174 } 1175 List [ 1176 ObjectInList { 1177 } 1178 ListInList [ 1179 ] 1180 ] 1181 )"; 1182 1183 const char *JSONExpectedOut = R"({ 1184 "Object": { 1185 "ObjectInObject": {}, 1186 "ListInObject": [] 1187 }, 1188 "List": [ 1189 { 1190 "ObjectInList": {} 1191 }, 1192 { 1193 "ListInList": [] 1194 } 1195 ] 1196 })"; 1197 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 1198 } 1199