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, OS.str()); 34 StreamBuffer.clear(); 35 PrintFunc(NoPrettyPrintWriter); 36 EXPECT_EQ(NoPrettyPrintOut, OS.str()); 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"})", OS.str()); 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"])", OS.str()); 55 StreamBuffer.clear(); 56 { 57 JSONScopedPrinter NoScopeWriter(OS, /*PrettyPrint=*/false); 58 NoScopeWriter.printString("NoScope"); 59 } 60 EXPECT_EQ(R"("NoScope")", OS.str()); 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(), OS.str()); 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(), OS.str()); 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 TEST_F(ScopedPrinterTest, PrintNumber) { 513 constexpr float MaxFloat = std::numeric_limits<float>::max(); 514 constexpr float MinFloat = std::numeric_limits<float>::min(); 515 constexpr float InfFloat = std::numeric_limits<float>::infinity(); 516 const float NaNFloat = std::nanf("1"); 517 constexpr double MaxDouble = std::numeric_limits<double>::max(); 518 constexpr double MinDouble = std::numeric_limits<double>::min(); 519 constexpr double InfDouble = std::numeric_limits<double>::infinity(); 520 const double NaNDouble = std::nan("1"); 521 522 auto PrintFunc = [&](ScopedPrinter &W) { 523 uint64_t Unsigned64Max = std::numeric_limits<uint64_t>::max(); 524 uint64_t Unsigned64Min = std::numeric_limits<uint64_t>::min(); 525 W.printNumber("uint64_t-max", Unsigned64Max); 526 W.printNumber("uint64_t-min", Unsigned64Min); 527 528 uint32_t Unsigned32Max = std::numeric_limits<uint32_t>::max(); 529 uint32_t Unsigned32Min = std::numeric_limits<uint32_t>::min(); 530 W.printNumber("uint32_t-max", Unsigned32Max); 531 W.printNumber("uint32_t-min", Unsigned32Min); 532 533 uint16_t Unsigned16Max = std::numeric_limits<uint16_t>::max(); 534 uint16_t Unsigned16Min = std::numeric_limits<uint16_t>::min(); 535 W.printNumber("uint16_t-max", Unsigned16Max); 536 W.printNumber("uint16_t-min", Unsigned16Min); 537 538 uint8_t Unsigned8Max = std::numeric_limits<uint8_t>::max(); 539 uint8_t Unsigned8Min = std::numeric_limits<uint8_t>::min(); 540 W.printNumber("uint8_t-max", Unsigned8Max); 541 W.printNumber("uint8_t-min", Unsigned8Min); 542 543 int64_t Signed64Max = std::numeric_limits<int64_t>::max(); 544 int64_t Signed64Min = std::numeric_limits<int64_t>::min(); 545 W.printNumber("int64_t-max", Signed64Max); 546 W.printNumber("int64_t-min", Signed64Min); 547 548 int32_t Signed32Max = std::numeric_limits<int32_t>::max(); 549 int32_t Signed32Min = std::numeric_limits<int32_t>::min(); 550 W.printNumber("int32_t-max", Signed32Max); 551 W.printNumber("int32_t-min", Signed32Min); 552 553 int16_t Signed16Max = std::numeric_limits<int16_t>::max(); 554 int16_t Signed16Min = std::numeric_limits<int16_t>::min(); 555 W.printNumber("int16_t-max", Signed16Max); 556 W.printNumber("int16_t-min", Signed16Min); 557 558 int8_t Signed8Max = std::numeric_limits<int8_t>::max(); 559 int8_t Signed8Min = std::numeric_limits<int8_t>::min(); 560 W.printNumber("int8_t-max", Signed8Max); 561 W.printNumber("int8_t-min", Signed8Min); 562 563 APSInt LargeNum("9999999999999999999999"); 564 W.printNumber("apsint", LargeNum); 565 566 W.printNumber("label", "value", 0); 567 568 W.printNumber("float-max", MaxFloat); 569 W.printNumber("float-min", MinFloat); 570 W.printNumber("float-inf", InfFloat); 571 W.printNumber("float-nan", NaNFloat); 572 W.printNumber("float-42.0", 42.0f); 573 W.printNumber("float-42.5625", 42.5625f); 574 575 W.printNumber("double-max", MaxDouble); 576 W.printNumber("double-min", MinDouble); 577 W.printNumber("double-inf", InfDouble); 578 W.printNumber("double-nan", NaNDouble); 579 W.printNumber("double-42.0", 42.0); 580 W.printNumber("double-42.5625", 42.5625); 581 }; 582 583 // Make sure when we check floating point representation we avoid 584 // implementation defined behavior. So format the max float/double, instead of 585 // hard coding it in the tests. Note: we can't just use std::to_string(), 586 // since we format the float in PrintNumber(). This isn't required for JSON 587 // formatting, since it uses exponents, which will be consistent. However, 588 // NaN and INF may be printed differently, (like AIX), so we still need to 589 // handle those cases for JSON checking. 590 591 // Allocate a buffer large enough to represent large floating point values 592 // and construct the string representation for them there. 593 char Buf[512]; 594 595 format("%5.1f", MaxFloat).snprint(Buf, sizeof(Buf)); 596 std::string MaxFloatStr(Buf); 597 598 format("%5.1f", MaxDouble).snprint(Buf, sizeof(Buf)); 599 std::string MaxDoubleStr(Buf); 600 601 format("%5.1f", InfFloat).snprint(Buf, sizeof(Buf)); 602 std::string InfFloatStr(Buf); 603 604 format("%5.1f", InfDouble).snprint(Buf, sizeof(Buf)); 605 std::string InfDoubleStr(Buf); 606 607 format("%5.1f", NaNFloat).snprint(Buf, sizeof(Buf)); 608 std::string NaNFloatStr(Buf); 609 610 format("%5.1f", NaNDouble).snprint(Buf, sizeof(Buf)); 611 std::string NaNDoubleStr(Buf); 612 613 format("%.*g", InfFloat).snprint(Buf, sizeof(Buf)); 614 std::string JsonInfFloatStr(Buf); 615 616 format("%.*g", InfDouble).snprint(Buf, sizeof(Buf)); 617 std::string JsonInfDoubleStr(Buf); 618 619 format("%.*g", NaNFloat).snprint(Buf, sizeof(Buf)); 620 std::string JsonNaNFloatStr(Buf); 621 622 format("%.*g", NaNDouble).snprint(Buf, sizeof(Buf)); 623 std::string JsonNaNDoubleStr(Buf); 624 625 626 std::string ExpectedOut = Twine( 627 R"(uint64_t-max: 18446744073709551615 628 uint64_t-min: 0 629 uint32_t-max: 4294967295 630 uint32_t-min: 0 631 uint16_t-max: 65535 632 uint16_t-min: 0 633 uint8_t-max: 255 634 uint8_t-min: 0 635 int64_t-max: 9223372036854775807 636 int64_t-min: -9223372036854775808 637 int32_t-max: 2147483647 638 int32_t-min: -2147483648 639 int16_t-max: 32767 640 int16_t-min: -32768 641 int8_t-max: 127 642 int8_t-min: -128 643 apsint: 9999999999999999999999 644 label: value (0) 645 float-max: )" + MaxFloatStr + R"( 646 float-min: 0.0 647 float-inf: )" + InfFloatStr + R"( 648 float-nan: )" + NaNFloatStr + R"( 649 float-42.0: 42.0 650 float-42.5625: 42.6 651 double-max: )" + MaxDoubleStr + 652 R"( 653 double-min: 0.0 654 double-inf: )" + InfDoubleStr + R"( 655 double-nan: )" + NaNDoubleStr + R"( 656 double-42.0: 42.0 657 double-42.5625: 42.6 658 )") 659 .str(); 660 661 std::string JSONExpectedOut = Twine(R"({ 662 "uint64_t-max": 18446744073709551615, 663 "uint64_t-min": 0, 664 "uint32_t-max": 4294967295, 665 "uint32_t-min": 0, 666 "uint16_t-max": 65535, 667 "uint16_t-min": 0, 668 "uint8_t-max": 255, 669 "uint8_t-min": 0, 670 "int64_t-max": 9223372036854775807, 671 "int64_t-min": -9223372036854775808, 672 "int32_t-max": 2147483647, 673 "int32_t-min": -2147483648, 674 "int16_t-max": 32767, 675 "int16_t-min": -32768, 676 "int8_t-max": 127, 677 "int8_t-min": -128, 678 "apsint": 9999999999999999999999, 679 "label": { 680 "Name": "value", 681 "Value": 0 682 }, 683 "float-max": 3.4028234663852886e+38, 684 "float-min": 1.1754943508222875e-38, 685 "float-inf": )" + JsonInfFloatStr + R"(, 686 "float-nan": )" + JsonNaNFloatStr + R"(, 687 "float-42.0": 42, 688 "float-42.5625": 42.5625, 689 "double-max": 1.7976931348623157e+308, 690 "double-min": 2.2250738585072014e-308, 691 "double-inf": )" + JsonInfDoubleStr + R"(, 692 "double-nan": )" + JsonNaNDoubleStr + R"(, 693 "double-42.0": 42, 694 "double-42.5625": 42.5625 695 })").str(); 696 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 697 } 698 699 TEST_F(ScopedPrinterTest, PrintBoolean) { 700 auto PrintFunc = [](ScopedPrinter &W) { 701 W.printBoolean("True", true); 702 W.printBoolean("False", false); 703 }; 704 705 const char *ExpectedOut = R"(True: Yes 706 False: No 707 )"; 708 709 const char *JSONExpectedOut = R"({ 710 "True": true, 711 "False": false 712 })"; 713 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 714 } 715 716 TEST_F(ScopedPrinterTest, PrintVersion) { 717 auto PrintFunc = [](ScopedPrinter &W) { 718 W.printVersion("Version", "123", "456", "789"); 719 }; 720 const char *ExpectedOut = R"(Version: 123.456.789 721 )"; 722 verifyScopedPrinter(ExpectedOut, PrintFunc); 723 } 724 725 TEST_F(ScopedPrinterTest, PrintList) { 726 auto PrintFunc = [](ScopedPrinter &W) { 727 const std::vector<uint64_t> EmptyList; 728 const std::vector<std::string> StringList = {"foo", "bar", "baz"}; 729 const bool BoolList[] = {true, false}; 730 const std::vector<uint64_t> Unsigned64List = { 731 std::numeric_limits<uint64_t>::max(), 732 std::numeric_limits<uint64_t>::min()}; 733 const std::vector<uint32_t> Unsigned32List = { 734 std::numeric_limits<uint32_t>::max(), 735 std::numeric_limits<uint32_t>::min()}; 736 const std::vector<uint16_t> Unsigned16List = { 737 std::numeric_limits<uint16_t>::max(), 738 std::numeric_limits<uint16_t>::min()}; 739 const std::vector<uint8_t> Unsigned8List = { 740 std::numeric_limits<uint8_t>::max(), 741 std::numeric_limits<uint8_t>::min()}; 742 const std::vector<int64_t> Signed64List = { 743 std::numeric_limits<int64_t>::max(), 744 std::numeric_limits<int64_t>::min()}; 745 const std::vector<int32_t> Signed32List = { 746 std::numeric_limits<int32_t>::max(), 747 std::numeric_limits<int32_t>::min()}; 748 const std::vector<int16_t> Signed16List = { 749 std::numeric_limits<int16_t>::max(), 750 std::numeric_limits<int16_t>::min()}; 751 const std::vector<int8_t> Signed8List = { 752 std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min()}; 753 const std::vector<APSInt> APSIntList = {APSInt("9999999999999999999999"), 754 APSInt("-9999999999999999999999")}; 755 W.printList("EmptyList", EmptyList); 756 W.printList("StringList", StringList); 757 W.printList("BoolList", ArrayRef(BoolList)); 758 W.printList("uint64List", Unsigned64List); 759 W.printList("uint32List", Unsigned32List); 760 W.printList("uint16List", Unsigned16List); 761 W.printList("uint8List", Unsigned8List); 762 W.printList("int64List", Signed64List); 763 W.printList("int32List", Signed32List); 764 W.printList("int16List", Signed16List); 765 W.printList("int8List", Signed8List); 766 W.printList("APSIntList", APSIntList); 767 }; 768 769 const char *ExpectedOut = R"(EmptyList: [] 770 StringList: [foo, bar, baz] 771 BoolList: [1, 0] 772 uint64List: [18446744073709551615, 0] 773 uint32List: [4294967295, 0] 774 uint16List: [65535, 0] 775 uint8List: [255, 0] 776 int64List: [9223372036854775807, -9223372036854775808] 777 int32List: [2147483647, -2147483648] 778 int16List: [32767, -32768] 779 int8List: [127, -128] 780 APSIntList: [9999999999999999999999, -9999999999999999999999] 781 )"; 782 783 const char *JSONExpectedOut = R"({ 784 "EmptyList": [], 785 "StringList": [ 786 "foo", 787 "bar", 788 "baz" 789 ], 790 "BoolList": [ 791 true, 792 false 793 ], 794 "uint64List": [ 795 18446744073709551615, 796 0 797 ], 798 "uint32List": [ 799 4294967295, 800 0 801 ], 802 "uint16List": [ 803 65535, 804 0 805 ], 806 "uint8List": [ 807 255, 808 0 809 ], 810 "int64List": [ 811 9223372036854775807, 812 -9223372036854775808 813 ], 814 "int32List": [ 815 2147483647, 816 -2147483648 817 ], 818 "int16List": [ 819 32767, 820 -32768 821 ], 822 "int8List": [ 823 127, 824 -128 825 ], 826 "APSIntList": [ 827 9999999999999999999999, 828 -9999999999999999999999 829 ] 830 })"; 831 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 832 } 833 834 TEST_F(ScopedPrinterTest, PrintListPrinter) { 835 auto PrintFunc = [](ScopedPrinter &W) { 836 const std::string StringList[] = {"a", "ab", "abc"}; 837 W.printList("StringSizeList", StringList, 838 [](raw_ostream &OS, StringRef Item) { OS << Item.size(); }); 839 }; 840 841 const char *ExpectedOut = R"(StringSizeList: [1, 2, 3] 842 )"; 843 verifyScopedPrinter(ExpectedOut, PrintFunc); 844 } 845 846 TEST_F(ScopedPrinterTest, PrintHex) { 847 auto PrintFunc = [](ScopedPrinter &W) { 848 W.printHex("HexNumber", 0x10); 849 W.printHex("HexLabel", "Name", 0x10); 850 }; 851 852 const char *ExpectedOut = R"(HexNumber: 0x10 853 HexLabel: Name (0x10) 854 )"; 855 856 const char *JSONExpectedOut = R"({ 857 "HexNumber": 16, 858 "HexLabel": { 859 "Name": "Name", 860 "Value": 16 861 } 862 })"; 863 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 864 } 865 866 TEST_F(ScopedPrinterTest, PrintHexList) { 867 auto PrintFunc = [](ScopedPrinter &W) { 868 const uint64_t HexList[] = {0x1, 0x10, 0x100}; 869 W.printHexList("HexList", HexList); 870 }; 871 const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100] 872 )"; 873 874 const char *JSONExpectedOut = R"({ 875 "HexList": [ 876 1, 877 16, 878 256 879 ] 880 })"; 881 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 882 } 883 884 TEST_F(ScopedPrinterTest, PrintSymbolOffset) { 885 auto PrintFunc = [](ScopedPrinter &W) { 886 W.printSymbolOffset("SymbolOffset", "SymbolName", 0x10); 887 W.printSymbolOffset("NoSymbolOffset", "SymbolName", 0); 888 }; 889 const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10 890 NoSymbolOffset: SymbolName+0x0 891 )"; 892 893 const char *JSONExpectedOut = R"({ 894 "SymbolOffset": { 895 "SymName": "SymbolName", 896 "Offset": 16 897 }, 898 "NoSymbolOffset": { 899 "SymName": "SymbolName", 900 "Offset": 0 901 } 902 })"; 903 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 904 } 905 906 TEST_F(ScopedPrinterTest, PrintString) { 907 auto PrintFunc = [](ScopedPrinter &W) { 908 const StringRef StringRefValue("Value"); 909 const std::string StringValue = "Value"; 910 const char *CharArrayValue = "Value"; 911 W.printString("StringRef", StringRefValue); 912 W.printString("String", StringValue); 913 W.printString("CharArray", CharArrayValue); 914 ListScope L(W, "StringList"); 915 W.printString(StringRefValue); 916 }; 917 918 const char *ExpectedOut = R"(StringRef: Value 919 String: Value 920 CharArray: Value 921 StringList [ 922 Value 923 ] 924 )"; 925 926 const char *JSONExpectedOut = R"({ 927 "StringRef": "Value", 928 "String": "Value", 929 "CharArray": "Value", 930 "StringList": [ 931 "Value" 932 ] 933 })"; 934 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 935 } 936 937 TEST_F(ScopedPrinterTest, PrintBinary) { 938 auto PrintFunc = [](ScopedPrinter &W) { 939 std::vector<uint8_t> IntArray = {70, 111, 111, 66, 97, 114}; 940 std::vector<char> CharArray = {'F', 'o', 'o', 'B', 'a', 'r'}; 941 std::vector<uint8_t> InvalidChars = {255, 255}; 942 W.printBinary("Binary1", "FooBar", IntArray); 943 W.printBinary("Binary2", "FooBar", CharArray); 944 W.printBinary("Binary3", IntArray); 945 W.printBinary("Binary4", CharArray); 946 W.printBinary("Binary5", StringRef("FooBar")); 947 W.printBinary("Binary6", StringRef("Multiple Line FooBar")); 948 W.printBinaryBlock("Binary7", IntArray, 20); 949 W.printBinaryBlock("Binary8", IntArray); 950 W.printBinaryBlock("Binary9", "FooBar"); 951 W.printBinaryBlock("Binary10", "Multiple Line FooBar"); 952 W.printBinaryBlock("Binary11", InvalidChars); 953 }; 954 955 const char *ExpectedOut = R"(Binary1: FooBar (46 6F 6F 42 61 72) 956 Binary2: FooBar (46 6F 6F 42 61 72) 957 Binary3: (46 6F 6F 42 61 72) 958 Binary4: (46 6F 6F 42 61 72) 959 Binary5: (46 6F 6F 42 61 72) 960 Binary6 ( 961 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo| 962 0010: 6F426172 |oBar| 963 ) 964 Binary7 ( 965 0014: 466F6F42 6172 |FooBar| 966 ) 967 Binary8 ( 968 0000: 466F6F42 6172 |FooBar| 969 ) 970 Binary9 ( 971 0000: 466F6F42 6172 |FooBar| 972 ) 973 Binary10 ( 974 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo| 975 0010: 6F426172 |oBar| 976 ) 977 Binary11 ( 978 0000: FFFF |..| 979 ) 980 )"; 981 982 const char *JSONExpectedOut = R"({ 983 "Binary1": { 984 "Value": "FooBar", 985 "Offset": 0, 986 "Bytes": [ 987 70, 988 111, 989 111, 990 66, 991 97, 992 114 993 ] 994 }, 995 "Binary2": { 996 "Value": "FooBar", 997 "Offset": 0, 998 "Bytes": [ 999 70, 1000 111, 1001 111, 1002 66, 1003 97, 1004 114 1005 ] 1006 }, 1007 "Binary3": { 1008 "Offset": 0, 1009 "Bytes": [ 1010 70, 1011 111, 1012 111, 1013 66, 1014 97, 1015 114 1016 ] 1017 }, 1018 "Binary4": { 1019 "Offset": 0, 1020 "Bytes": [ 1021 70, 1022 111, 1023 111, 1024 66, 1025 97, 1026 114 1027 ] 1028 }, 1029 "Binary5": { 1030 "Offset": 0, 1031 "Bytes": [ 1032 70, 1033 111, 1034 111, 1035 66, 1036 97, 1037 114 1038 ] 1039 }, 1040 "Binary6": { 1041 "Offset": 0, 1042 "Bytes": [ 1043 77, 1044 117, 1045 108, 1046 116, 1047 105, 1048 112, 1049 108, 1050 101, 1051 32, 1052 76, 1053 105, 1054 110, 1055 101, 1056 32, 1057 70, 1058 111, 1059 111, 1060 66, 1061 97, 1062 114 1063 ] 1064 }, 1065 "Binary7": { 1066 "Offset": 20, 1067 "Bytes": [ 1068 70, 1069 111, 1070 111, 1071 66, 1072 97, 1073 114 1074 ] 1075 }, 1076 "Binary8": { 1077 "Offset": 0, 1078 "Bytes": [ 1079 70, 1080 111, 1081 111, 1082 66, 1083 97, 1084 114 1085 ] 1086 }, 1087 "Binary9": { 1088 "Offset": 0, 1089 "Bytes": [ 1090 70, 1091 111, 1092 111, 1093 66, 1094 97, 1095 114 1096 ] 1097 }, 1098 "Binary10": { 1099 "Offset": 0, 1100 "Bytes": [ 1101 77, 1102 117, 1103 108, 1104 116, 1105 105, 1106 112, 1107 108, 1108 101, 1109 32, 1110 76, 1111 105, 1112 110, 1113 101, 1114 32, 1115 70, 1116 111, 1117 111, 1118 66, 1119 97, 1120 114 1121 ] 1122 }, 1123 "Binary11": { 1124 "Offset": 0, 1125 "Bytes": [ 1126 255, 1127 255 1128 ] 1129 } 1130 })"; 1131 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 1132 } 1133 1134 TEST_F(ScopedPrinterTest, PrintObject) { 1135 auto PrintFunc = [](ScopedPrinter &W) { W.printObject("Object", "Value"); }; 1136 1137 const char *ExpectedOut = R"(Object: Value 1138 )"; 1139 1140 const char *JSONExpectedOut = R"({ 1141 "Object": "Value" 1142 })"; 1143 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 1144 } 1145 1146 TEST_F(ScopedPrinterTest, StartLine) { 1147 auto PrintFunc = [](ScopedPrinter &W) { 1148 W.startLine() << "|"; 1149 W.indent(2); 1150 W.startLine() << "|"; 1151 W.unindent(); 1152 W.startLine() << "|"; 1153 }; 1154 1155 const char *ExpectedOut = "| | |"; 1156 verifyScopedPrinter(ExpectedOut, PrintFunc); 1157 } 1158 1159 TEST_F(ScopedPrinterTest, GetOStream) { 1160 auto PrintFunc = [](ScopedPrinter &W) { W.getOStream() << "Test"; }; 1161 1162 const char *ExpectedOut = "Test"; 1163 verifyScopedPrinter(ExpectedOut, PrintFunc); 1164 } 1165 1166 TEST_F(ScopedPrinterTest, PrintScope) { 1167 auto PrintFunc = [](ScopedPrinter &W) { 1168 { 1169 DictScope O(W, "Object"); 1170 { DictScope OO(W, "ObjectInObject"); } 1171 { ListScope LO(W, "ListInObject"); } 1172 } 1173 { 1174 ListScope L(W, "List"); 1175 { DictScope OL(W, "ObjectInList"); } 1176 { ListScope LL(W, "ListInList"); } 1177 } 1178 }; 1179 1180 const char *ExpectedOut = R"(Object { 1181 ObjectInObject { 1182 } 1183 ListInObject [ 1184 ] 1185 } 1186 List [ 1187 ObjectInList { 1188 } 1189 ListInList [ 1190 ] 1191 ] 1192 )"; 1193 1194 const char *JSONExpectedOut = R"({ 1195 "Object": { 1196 "ObjectInObject": {}, 1197 "ListInObject": [] 1198 }, 1199 "List": [ 1200 { 1201 "ObjectInList": {} 1202 }, 1203 { 1204 "ListInList": [] 1205 } 1206 ] 1207 })"; 1208 verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc); 1209 } 1210