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