xref: /llvm-project/llvm/unittests/Support/ScopedPrinterTest.cpp (revision d25a65030bc136ab9dfe68a9c3bc10399c204364)
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