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