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