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