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