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 <vector> 13 14 using namespace llvm; 15 16 class ScopedPrinterTest : public ::testing::Test { 17 protected: 18 std::string StreamBuffer; 19 raw_string_ostream OS; 20 ScopedPrinter Writer; 21 22 ScopedPrinterTest() : OS(StreamBuffer), Writer(OS) {} 23 24 using PrintFunc = function_ref<void(ScopedPrinter &)>; 25 26 void verifyScopedPrinter(StringRef Expected, PrintFunc Func) { 27 Func(Writer); 28 Writer.flush(); 29 EXPECT_EQ(Expected.str(), OS.str()); 30 } 31 }; 32 33 TEST_F(ScopedPrinterTest, Indent) { 34 auto PrintFunc = [](ScopedPrinter &W) { 35 W.printString("|"); 36 W.indent(); 37 W.printString("|"); 38 W.indent(2); 39 W.printString("|"); 40 }; 41 42 const char *ExpectedOut = R"(| 43 | 44 | 45 )"; 46 verifyScopedPrinter(ExpectedOut, PrintFunc); 47 } 48 49 TEST_F(ScopedPrinterTest, Unindent) { 50 auto PrintFunc = [](ScopedPrinter &W) { 51 W.indent(3); 52 W.printString("|"); 53 W.unindent(2); 54 W.printString("|"); 55 W.unindent(); 56 W.printString("|"); 57 W.unindent(); 58 W.printString("|"); 59 }; 60 61 const char *ExpectedOut = R"( | 62 | 63 | 64 | 65 )"; 66 verifyScopedPrinter(ExpectedOut, PrintFunc); 67 } 68 69 TEST_F(ScopedPrinterTest, ResetIndent) { 70 auto PrintFunc = [](ScopedPrinter &W) { 71 W.indent(4); 72 W.printString("|"); 73 W.resetIndent(); 74 W.printString("|"); 75 }; 76 77 const char *ExpectedOut = R"( | 78 | 79 )"; 80 verifyScopedPrinter(ExpectedOut, PrintFunc); 81 } 82 83 TEST_F(ScopedPrinterTest, PrintIndent) { 84 auto PrintFunc = [](ScopedPrinter &W) { 85 W.printIndent(); 86 W.printString("|"); 87 W.indent(); 88 W.printIndent(); 89 W.printString("|"); 90 }; 91 92 const char *ExpectedOut = R"(| 93 | 94 )"; 95 verifyScopedPrinter(ExpectedOut, PrintFunc); 96 } 97 98 TEST_F(ScopedPrinterTest, GetIndentLevel) { 99 EXPECT_EQ(Writer.getIndentLevel(), 0); 100 Writer.indent(); 101 EXPECT_EQ(Writer.getIndentLevel(), 1); 102 Writer.indent(); 103 EXPECT_EQ(Writer.getIndentLevel(), 2); 104 Writer.unindent(); 105 EXPECT_EQ(Writer.getIndentLevel(), 1); 106 Writer.indent(); 107 Writer.resetIndent(); 108 EXPECT_EQ(Writer.getIndentLevel(), 0); 109 Writer.unindent(); 110 EXPECT_EQ(Writer.getIndentLevel(), 0); 111 Writer.indent(); 112 EXPECT_EQ(Writer.getIndentLevel(), 1); 113 } 114 115 TEST_F(ScopedPrinterTest, SetPrefix) { 116 auto PrintFunc = [](ScopedPrinter &W) { 117 W.setPrefix("Prefix1"); 118 W.indent(); 119 W.printIndent(); 120 W.printString("|"); 121 W.unindent(); 122 W.printIndent(); 123 W.printString("|"); 124 W.setPrefix("Prefix2"); 125 W.printIndent(); 126 W.printString("|"); 127 }; 128 129 const char *ExpectedOut = R"(Prefix1 Prefix1 | 130 Prefix1Prefix1| 131 Prefix2Prefix2| 132 )"; 133 verifyScopedPrinter(ExpectedOut, PrintFunc); 134 } 135 136 TEST_F(ScopedPrinterTest, PrintEnum) { 137 auto PrintFunc = [](ScopedPrinter &W) { 138 const EnumEntry<int> EnumList[] = {{"Name1", "AltName1", 1}, 139 {"Name2", "AltName2", 2}, 140 {"Name3", "AltName3", 3}, 141 {"Name4", "AltName4", 2}}; 142 EnumEntry<int> OtherEnum{"Name5", "AltName5", 5}; 143 W.printEnum("Exists", EnumList[1].Value, makeArrayRef(EnumList)); 144 W.printEnum("DoesNotExist", OtherEnum.Value, makeArrayRef(EnumList)); 145 }; 146 147 const char *ExpectedOut = R"(Exists: Name2 (0x2) 148 DoesNotExist: 0x5 149 )"; 150 verifyScopedPrinter(ExpectedOut, PrintFunc); 151 } 152 153 TEST_F(ScopedPrinterTest, PrintFlag) { 154 auto PrintFunc = [](ScopedPrinter &W) { 155 const EnumEntry<uint16_t> SingleBitFlags[] = { 156 {"Name0", "AltName0", 0}, 157 {"Name1", "AltName1", 1}, 158 {"Name2", "AltName2", 1 << 1}, 159 {"Name3", "AltName3", 1 << 2}}; 160 const EnumEntry<uint16_t> UnsortedFlags[] = { 161 {"C", "c", 1}, {"B", "b", 1 << 1}, {"A", "a", 1 << 2}}; 162 const EnumEntry<uint16_t> EnumFlags[] = { 163 {"FirstByte1", "First1", 0x1u}, {"FirstByte2", "First2", 0x2u}, 164 {"FirstByte3", "First3", 0x3u}, {"SecondByte1", "Second1", 0x10u}, 165 {"SecondByte2", "Second2", 0x20u}, {"SecondByte3", "Second3", 0x30u}, 166 {"ThirdByte1", "Third1", 0x100u}, {"ThirdByte2", "Third2", 0x200u}, 167 {"ThirdByte3", "Third3", 0x300u}}; 168 W.printFlags("ZeroFlag", 0, makeArrayRef(SingleBitFlags)); 169 W.printFlags("NoFlag", 1 << 3, makeArrayRef(SingleBitFlags)); 170 W.printFlags("Flag1", SingleBitFlags[1].Value, 171 makeArrayRef(SingleBitFlags)); 172 W.printFlags("Flag1&3", (1 << 2) + 1, makeArrayRef(SingleBitFlags)); 173 174 W.printFlags("ZeroFlagRaw", 0); 175 W.printFlags("NoFlagRaw", 1 << 3); 176 W.printFlags("Flag1Raw", SingleBitFlags[1].Value); 177 W.printFlags("Flag1&3Raw", (1 << 2) + 1); 178 179 W.printFlags("FlagSorted", (1 << 2) + (1 << 1) + 1, 180 makeArrayRef(UnsortedFlags)); 181 182 uint16_t NoBitMask = 0; 183 uint16_t FirstByteMask = 0xFu; 184 uint16_t SecondByteMask = 0xF0u; 185 uint16_t ThirdByteMask = 0xF00u; 186 W.printFlags("NoBitMask", 0xFFFu, makeArrayRef(EnumFlags), NoBitMask); 187 W.printFlags("FirstByteMask", 0x3u, makeArrayRef(EnumFlags), FirstByteMask); 188 W.printFlags("SecondByteMask", 0x30u, makeArrayRef(EnumFlags), 189 SecondByteMask); 190 W.printFlags("ValueOutsideMask", 0x1u, makeArrayRef(EnumFlags), 191 SecondByteMask); 192 W.printFlags("FirstSecondByteMask", 0xFFu, makeArrayRef(EnumFlags), 193 FirstByteMask, SecondByteMask); 194 W.printFlags("FirstSecondThirdByteMask", 0x333u, makeArrayRef(EnumFlags), 195 FirstByteMask, SecondByteMask, ThirdByteMask); 196 }; 197 198 const char *ExpectedOut = R"(ZeroFlag [ (0x0) 199 ] 200 NoFlag [ (0x8) 201 ] 202 Flag1 [ (0x1) 203 Name1 (0x1) 204 ] 205 Flag1&3 [ (0x5) 206 Name1 (0x1) 207 Name3 (0x4) 208 ] 209 ZeroFlagRaw [ (0x0) 210 ] 211 NoFlagRaw [ (0x8) 212 0x8 213 ] 214 Flag1Raw [ (0x1) 215 0x1 216 ] 217 Flag1&3Raw [ (0x5) 218 0x1 219 0x4 220 ] 221 FlagSorted [ (0x7) 222 A (0x4) 223 B (0x2) 224 C (0x1) 225 ] 226 NoBitMask [ (0xFFF) 227 FirstByte1 (0x1) 228 FirstByte2 (0x2) 229 FirstByte3 (0x3) 230 SecondByte1 (0x10) 231 SecondByte2 (0x20) 232 SecondByte3 (0x30) 233 ThirdByte1 (0x100) 234 ThirdByte2 (0x200) 235 ThirdByte3 (0x300) 236 ] 237 FirstByteMask [ (0x3) 238 FirstByte3 (0x3) 239 ] 240 SecondByteMask [ (0x30) 241 SecondByte3 (0x30) 242 ] 243 ValueOutsideMask [ (0x1) 244 FirstByte1 (0x1) 245 ] 246 FirstSecondByteMask [ (0xFF) 247 ] 248 FirstSecondThirdByteMask [ (0x333) 249 FirstByte3 (0x3) 250 SecondByte3 (0x30) 251 ThirdByte3 (0x300) 252 ] 253 )"; 254 verifyScopedPrinter(ExpectedOut, PrintFunc); 255 } 256 257 TEST_F(ScopedPrinterTest, PrintNumber) { 258 auto PrintFunc = [](ScopedPrinter &W) { 259 uint64_t Unsigned64Max = std::numeric_limits<uint64_t>::max(); 260 uint64_t Unsigned64Min = std::numeric_limits<uint64_t>::min(); 261 W.printNumber("uint64_t-max", Unsigned64Max); 262 W.printNumber("uint64_t-min", Unsigned64Min); 263 264 uint32_t Unsigned32Max = std::numeric_limits<uint32_t>::max(); 265 uint32_t Unsigned32Min = std::numeric_limits<uint32_t>::min(); 266 W.printNumber("uint32_t-max", Unsigned32Max); 267 W.printNumber("uint32_t-min", Unsigned32Min); 268 269 uint16_t Unsigned16Max = std::numeric_limits<uint16_t>::max(); 270 uint16_t Unsigned16Min = std::numeric_limits<uint16_t>::min(); 271 W.printNumber("uint16_t-max", Unsigned16Max); 272 W.printNumber("uint16_t-min", Unsigned16Min); 273 274 uint8_t Unsigned8Max = std::numeric_limits<uint8_t>::max(); 275 uint8_t Unsigned8Min = std::numeric_limits<uint8_t>::min(); 276 W.printNumber("uint8_t-max", Unsigned8Max); 277 W.printNumber("uint8_t-min", Unsigned8Min); 278 279 int64_t Signed64Max = std::numeric_limits<int64_t>::max(); 280 int64_t Signed64Min = std::numeric_limits<int64_t>::min(); 281 W.printNumber("int64_t-max", Signed64Max); 282 W.printNumber("int64_t-min", Signed64Min); 283 284 int32_t Signed32Max = std::numeric_limits<int32_t>::max(); 285 int32_t Signed32Min = std::numeric_limits<int32_t>::min(); 286 W.printNumber("int32_t-max", Signed32Max); 287 W.printNumber("int32_t-min", Signed32Min); 288 289 int16_t Signed16Max = std::numeric_limits<int16_t>::max(); 290 int16_t Signed16Min = std::numeric_limits<int16_t>::min(); 291 W.printNumber("int16_t-max", Signed16Max); 292 W.printNumber("int16_t-min", Signed16Min); 293 294 int8_t Signed8Max = std::numeric_limits<int8_t>::max(); 295 int8_t Signed8Min = std::numeric_limits<int8_t>::min(); 296 W.printNumber("int8_t-max", Signed8Max); 297 W.printNumber("int8_t-min", Signed8Min); 298 299 APSInt LargeNum("9999999999999999999999"); 300 W.printNumber("apsint", LargeNum); 301 302 W.printNumber("label", "value", 0); 303 }; 304 305 const char *ExpectedOut = R"(uint64_t-max: 18446744073709551615 306 uint64_t-min: 0 307 uint32_t-max: 4294967295 308 uint32_t-min: 0 309 uint16_t-max: 65535 310 uint16_t-min: 0 311 uint8_t-max: 255 312 uint8_t-min: 0 313 int64_t-max: 9223372036854775807 314 int64_t-min: -9223372036854775808 315 int32_t-max: 2147483647 316 int32_t-min: -2147483648 317 int16_t-max: 32767 318 int16_t-min: -32768 319 int8_t-max: 127 320 int8_t-min: -128 321 apsint: 9999999999999999999999 322 label: value (0) 323 )"; 324 verifyScopedPrinter(ExpectedOut, PrintFunc); 325 } 326 327 TEST_F(ScopedPrinterTest, PrintBoolean) { 328 auto PrintFunc = [](ScopedPrinter &W) { 329 W.printBoolean("True", true); 330 W.printBoolean("False", false); 331 }; 332 333 const char *ExpectedOut = R"(True: Yes 334 False: No 335 )"; 336 verifyScopedPrinter(ExpectedOut, PrintFunc); 337 } 338 339 TEST_F(ScopedPrinterTest, PrintVersion) { 340 auto PrintFunc = [](ScopedPrinter &W) { 341 W.printVersion("Version", "123", "456", "789"); 342 }; 343 const char *ExpectedOut = R"(Version: 123.456.789 344 )"; 345 verifyScopedPrinter(ExpectedOut, PrintFunc); 346 } 347 348 TEST_F(ScopedPrinterTest, PrintList) { 349 auto PrintFunc = [](ScopedPrinter &W) { 350 const std::vector<uint64_t> EmptyList; 351 const std::vector<std::string> StringList = {"foo", "bar", "baz"}; 352 const bool BoolList[] = {true, false}; 353 const std::vector<uint64_t> Unsigned64List = { 354 std::numeric_limits<uint64_t>::max(), 355 std::numeric_limits<uint64_t>::min()}; 356 const std::vector<uint32_t> Unsigned32List = { 357 std::numeric_limits<uint32_t>::max(), 358 std::numeric_limits<uint32_t>::min()}; 359 const std::vector<uint16_t> Unsigned16List = { 360 std::numeric_limits<uint16_t>::max(), 361 std::numeric_limits<uint16_t>::min()}; 362 const std::vector<uint8_t> Unsigned8List = { 363 std::numeric_limits<uint8_t>::max(), 364 std::numeric_limits<uint8_t>::min()}; 365 const std::vector<int64_t> Signed64List = { 366 std::numeric_limits<int64_t>::max(), 367 std::numeric_limits<int64_t>::min()}; 368 const std::vector<int32_t> Signed32List = { 369 std::numeric_limits<int32_t>::max(), 370 std::numeric_limits<int32_t>::min()}; 371 const std::vector<int16_t> Signed16List = { 372 std::numeric_limits<int16_t>::max(), 373 std::numeric_limits<int16_t>::min()}; 374 const std::vector<int8_t> Signed8List = { 375 std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min()}; 376 const std::vector<APSInt> APSIntList = {APSInt("9999999999999999999999"), 377 APSInt("-9999999999999999999999")}; 378 W.printList("EmptyList", EmptyList); 379 W.printList("StringList", StringList); 380 W.printList("BoolList", makeArrayRef(BoolList)); 381 W.printList("uint64List", Unsigned64List); 382 W.printList("uint32List", Unsigned32List); 383 W.printList("uint16List", Unsigned16List); 384 W.printList("uint8List", Unsigned8List); 385 W.printList("int64List", Signed64List); 386 W.printList("int32List", Signed32List); 387 W.printList("int16List", Signed16List); 388 W.printList("int8List", Signed8List); 389 W.printList("APSIntList", APSIntList); 390 }; 391 392 const char *ExpectedOut = R"(EmptyList: [] 393 StringList: [foo, bar, baz] 394 BoolList: [1, 0] 395 uint64List: [18446744073709551615, 0] 396 uint32List: [4294967295, 0] 397 uint16List: [65535, 0] 398 uint8List: [255, 0] 399 int64List: [9223372036854775807, -9223372036854775808] 400 int32List: [2147483647, -2147483648] 401 int16List: [32767, -32768] 402 int8List: [127, -128] 403 APSIntList: [9999999999999999999999, -9999999999999999999999] 404 )"; 405 verifyScopedPrinter(ExpectedOut, PrintFunc); 406 } 407 408 TEST_F(ScopedPrinterTest, PrintListPrinter) { 409 auto PrintFunc = [](ScopedPrinter &W) { 410 const std::string StringList[] = {"a", "ab", "abc"}; 411 W.printList("StringSizeList", StringList, 412 [](raw_ostream &OS, StringRef Item) { OS << Item.size(); }); 413 }; 414 415 const char *ExpectedOut = R"(StringSizeList: [1, 2, 3] 416 )"; 417 verifyScopedPrinter(ExpectedOut, PrintFunc); 418 } 419 420 TEST_F(ScopedPrinterTest, PrintHex) { 421 auto PrintFunc = [](ScopedPrinter &W) { 422 W.printHex("HexNumber", 0x10); 423 W.printHex("HexLabel", "Name", 0x10); 424 }; 425 426 const char *ExpectedOut = R"(HexNumber: 0x10 427 HexLabel: Name (0x10) 428 )"; 429 verifyScopedPrinter(ExpectedOut, PrintFunc); 430 } 431 432 TEST_F(ScopedPrinterTest, PrintHexList) { 433 auto PrintFunc = [](ScopedPrinter &W) { 434 const uint64_t HexList[] = {0x1, 0x10, 0x100}; 435 W.printHexList("HexList", HexList); 436 }; 437 const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100] 438 )"; 439 verifyScopedPrinter(ExpectedOut, PrintFunc); 440 } 441 442 TEST_F(ScopedPrinterTest, PrintSymbolOffset) { 443 auto PrintFunc = [](ScopedPrinter &W) { 444 W.printSymbolOffset("SymbolOffset", "SymbolName", 0x10); 445 W.printSymbolOffset("NoSymbolOffset", "SymbolName", 0); 446 }; 447 const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10 448 NoSymbolOffset: SymbolName+0x0 449 )"; 450 verifyScopedPrinter(ExpectedOut, PrintFunc); 451 } 452 453 TEST_F(ScopedPrinterTest, PrintString) { 454 auto PrintFunc = [](ScopedPrinter &W) { 455 const StringRef StringRefValue("Value"); 456 const std::string StringValue = "Value"; 457 const char *CharArrayValue = "Value"; 458 W.printString("StringRef", StringRefValue); 459 W.printString("String", StringValue); 460 W.printString("CharArray", CharArrayValue); 461 ListScope L(W, "StringList"); 462 W.printString(StringRefValue); 463 }; 464 465 const char *ExpectedOut = R"(StringRef: Value 466 String: Value 467 CharArray: Value 468 StringList [ 469 Value 470 ] 471 )"; 472 verifyScopedPrinter(ExpectedOut, PrintFunc); 473 } 474 475 TEST_F(ScopedPrinterTest, PrintBinary) { 476 auto PrintFunc = [](ScopedPrinter &W) { 477 std::vector<uint8_t> IntArray = {70, 111, 111, 66, 97, 114}; 478 std::vector<char> CharArray = {'F', 'o', 'o', 'B', 'a', 'r'}; 479 std::vector<uint8_t> InvalidChars = {255, 255}; 480 W.printBinary("Binary1", "FooBar", IntArray); 481 W.printBinary("Binary2", "FooBar", CharArray); 482 W.printBinary("Binary3", IntArray); 483 W.printBinary("Binary4", CharArray); 484 W.printBinary("Binary5", StringRef("FooBar")); 485 W.printBinary("Binary6", StringRef("Multiple Line FooBar")); 486 W.printBinaryBlock("Binary7", IntArray, 20); 487 W.printBinaryBlock("Binary8", IntArray); 488 W.printBinaryBlock("Binary9", "FooBar"); 489 W.printBinaryBlock("Binary10", "Multiple Line FooBar"); 490 W.printBinaryBlock("Binary11", InvalidChars); 491 }; 492 493 const char *ExpectedOut = R"(Binary1: FooBar (46 6F 6F 42 61 72) 494 Binary2: FooBar (46 6F 6F 42 61 72) 495 Binary3: (46 6F 6F 42 61 72) 496 Binary4: (46 6F 6F 42 61 72) 497 Binary5: (46 6F 6F 42 61 72) 498 Binary6 ( 499 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo| 500 0010: 6F426172 |oBar| 501 ) 502 Binary7 ( 503 0014: 466F6F42 6172 |FooBar| 504 ) 505 Binary8 ( 506 0000: 466F6F42 6172 |FooBar| 507 ) 508 Binary9 ( 509 0000: 466F6F42 6172 |FooBar| 510 ) 511 Binary10 ( 512 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo| 513 0010: 6F426172 |oBar| 514 ) 515 Binary11 ( 516 0000: FFFF |..| 517 ) 518 )"; 519 verifyScopedPrinter(ExpectedOut, PrintFunc); 520 } 521 522 TEST_F(ScopedPrinterTest, PrintObject) { 523 auto PrintFunc = [](ScopedPrinter &W) { W.printObject("Object", "Value"); }; 524 525 const char *ExpectedOut = R"(Object: Value 526 )"; 527 verifyScopedPrinter(ExpectedOut, PrintFunc); 528 } 529 530 TEST_F(ScopedPrinterTest, StartLine) { 531 auto PrintFunc = [](ScopedPrinter &W) { 532 W.startLine() << "|"; 533 W.indent(2); 534 W.startLine() << "|"; 535 W.unindent(); 536 W.startLine() << "|"; 537 }; 538 539 const char *ExpectedOut = "| | |"; 540 verifyScopedPrinter(ExpectedOut, PrintFunc); 541 } 542 543 TEST_F(ScopedPrinterTest, GetOStream) { 544 auto PrintFunc = [](ScopedPrinter &W) { W.getOStream() << "Test"; }; 545 546 const char *ExpectedOut = "Test"; 547 verifyScopedPrinter(ExpectedOut, PrintFunc); 548 } 549 550 TEST_F(ScopedPrinterTest, PrintScope) { 551 auto PrintFunc = [](ScopedPrinter &W) { 552 { 553 DictScope O(W, "Object"); 554 { DictScope OO(W, "ObjectInObject"); } 555 { ListScope LO(W, "ListInObject"); } 556 } 557 { 558 ListScope L(W, "List"); 559 { DictScope OL(W, "ObjectInList"); } 560 { ListScope LL(W, "ListInList"); } 561 } 562 }; 563 564 const char *ExpectedOut = R"(Object { 565 ObjectInObject { 566 } 567 ListInObject [ 568 ] 569 } 570 List [ 571 ObjectInList { 572 } 573 ListInList [ 574 ] 575 ] 576 )"; 577 verifyScopedPrinter(ExpectedOut, PrintFunc); 578 } 579