xref: /llvm-project/llvm/unittests/Support/ScopedPrinterTest.cpp (revision 77bab2a6f37af918a9133d1bb15551bd351b291e)
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, StreamBuffer);
34   StreamBuffer.clear();
35   PrintFunc(NoPrettyPrintWriter);
36   EXPECT_EQ(NoPrettyPrintOut, StreamBuffer);
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"})", StreamBuffer);
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"])", StreamBuffer);
55   StreamBuffer.clear();
56   {
57     JSONScopedPrinter NoScopeWriter(OS, /*PrettyPrint=*/false);
58     NoScopeWriter.printString("NoScope");
59   }
60   EXPECT_EQ(R"("NoScope")", StreamBuffer);
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(), StreamBuffer);
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(), StreamBuffer);
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 // Format floats using the same format string as PrintNumber, so we can check
513 // the output on all platforms.
514 template <typename T,
515           std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
516 std::string formatFloatString(T Val) {
517   std::string Ret;
518   raw_string_ostream OS(Ret);
519   OS << format("%5.1f", Val);
520   return Ret;
521 }
522 
523 // Format floats using the same format string used in JSON, so we can check the
524 // output on all platforms.
525 template <typename T,
526           std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
527 std::string formatJsonFloatString(T Val) {
528   std::string Ret;
529   raw_string_ostream OS(Ret);
530   OS << format("%.*g", std::numeric_limits<double>::max_digits10, Val);
531   return Ret;
532 }
533 
534 TEST_F(ScopedPrinterTest, PrintNumber) {
535   constexpr float MaxFloat = std::numeric_limits<float>::max();
536   constexpr float MinFloat = std::numeric_limits<float>::min();
537   constexpr float InfFloat = std::numeric_limits<float>::infinity();
538   const float NaNFloat = std::nanf("1");
539   constexpr double MaxDouble = std::numeric_limits<double>::max();
540   constexpr double MinDouble = std::numeric_limits<double>::min();
541   constexpr double InfDouble = std::numeric_limits<double>::infinity();
542   const double NaNDouble = std::nan("1");
543 
544   auto PrintFunc = [&](ScopedPrinter &W) {
545     uint64_t Unsigned64Max = std::numeric_limits<uint64_t>::max();
546     uint64_t Unsigned64Min = std::numeric_limits<uint64_t>::min();
547     W.printNumber("uint64_t-max", Unsigned64Max);
548     W.printNumber("uint64_t-min", Unsigned64Min);
549 
550     uint32_t Unsigned32Max = std::numeric_limits<uint32_t>::max();
551     uint32_t Unsigned32Min = std::numeric_limits<uint32_t>::min();
552     W.printNumber("uint32_t-max", Unsigned32Max);
553     W.printNumber("uint32_t-min", Unsigned32Min);
554 
555     uint16_t Unsigned16Max = std::numeric_limits<uint16_t>::max();
556     uint16_t Unsigned16Min = std::numeric_limits<uint16_t>::min();
557     W.printNumber("uint16_t-max", Unsigned16Max);
558     W.printNumber("uint16_t-min", Unsigned16Min);
559 
560     uint8_t Unsigned8Max = std::numeric_limits<uint8_t>::max();
561     uint8_t Unsigned8Min = std::numeric_limits<uint8_t>::min();
562     W.printNumber("uint8_t-max", Unsigned8Max);
563     W.printNumber("uint8_t-min", Unsigned8Min);
564 
565     int64_t Signed64Max = std::numeric_limits<int64_t>::max();
566     int64_t Signed64Min = std::numeric_limits<int64_t>::min();
567     W.printNumber("int64_t-max", Signed64Max);
568     W.printNumber("int64_t-min", Signed64Min);
569 
570     int32_t Signed32Max = std::numeric_limits<int32_t>::max();
571     int32_t Signed32Min = std::numeric_limits<int32_t>::min();
572     W.printNumber("int32_t-max", Signed32Max);
573     W.printNumber("int32_t-min", Signed32Min);
574 
575     int16_t Signed16Max = std::numeric_limits<int16_t>::max();
576     int16_t Signed16Min = std::numeric_limits<int16_t>::min();
577     W.printNumber("int16_t-max", Signed16Max);
578     W.printNumber("int16_t-min", Signed16Min);
579 
580     int8_t Signed8Max = std::numeric_limits<int8_t>::max();
581     int8_t Signed8Min = std::numeric_limits<int8_t>::min();
582     W.printNumber("int8_t-max", Signed8Max);
583     W.printNumber("int8_t-min", Signed8Min);
584 
585     APSInt LargeNum("9999999999999999999999");
586     W.printNumber("apsint", LargeNum);
587 
588     W.printNumber("label", "value", 0);
589 
590     W.printNumber("float-max", MaxFloat);
591     W.printNumber("float-min", MinFloat);
592     W.printNumber("float-inf", InfFloat);
593     W.printNumber("float-nan", NaNFloat);
594     W.printNumber("float-42.0", 42.0f);
595     W.printNumber("float-42.5625", 42.5625f);
596 
597     W.printNumber("double-max", MaxDouble);
598     W.printNumber("double-min", MinDouble);
599     W.printNumber("double-inf", InfDouble);
600     W.printNumber("double-nan", NaNDouble);
601     W.printNumber("double-42.0", 42.0);
602     W.printNumber("double-42.5625", 42.5625);
603   };
604 
605   std::string ExpectedOut = Twine(
606                                 R"(uint64_t-max: 18446744073709551615
607 uint64_t-min: 0
608 uint32_t-max: 4294967295
609 uint32_t-min: 0
610 uint16_t-max: 65535
611 uint16_t-min: 0
612 uint8_t-max: 255
613 uint8_t-min: 0
614 int64_t-max: 9223372036854775807
615 int64_t-min: -9223372036854775808
616 int32_t-max: 2147483647
617 int32_t-min: -2147483648
618 int16_t-max: 32767
619 int16_t-min: -32768
620 int8_t-max: 127
621 int8_t-min: -128
622 apsint: 9999999999999999999999
623 label: value (0)
624 float-max: )" + formatFloatString(MaxFloat) +
625                                 R"(
626 float-min:   0.0
627 float-inf: )" + formatFloatString(InfFloat) +
628                                 R"(
629 float-nan: )" + formatFloatString(NaNFloat) +
630                                 R"(
631 float-42.0:  42.0
632 float-42.5625:  42.6
633 double-max: )" + formatFloatString(MaxDouble) +
634                                 R"(
635 double-min:   0.0
636 double-inf: )" + formatFloatString(InfDouble) +
637                                 R"(
638 double-nan: )" + formatFloatString(NaNDouble) +
639                                 R"(
640 double-42.0:  42.0
641 double-42.5625:  42.6
642 )")
643                                 .str();
644 
645   std::string JSONExpectedOut = Twine(R"({
646   "uint64_t-max": 18446744073709551615,
647   "uint64_t-min": 0,
648   "uint32_t-max": 4294967295,
649   "uint32_t-min": 0,
650   "uint16_t-max": 65535,
651   "uint16_t-min": 0,
652   "uint8_t-max": 255,
653   "uint8_t-min": 0,
654   "int64_t-max": 9223372036854775807,
655   "int64_t-min": -9223372036854775808,
656   "int32_t-max": 2147483647,
657   "int32_t-min": -2147483648,
658   "int16_t-max": 32767,
659   "int16_t-min": -32768,
660   "int8_t-max": 127,
661   "int8_t-min": -128,
662   "apsint": 9999999999999999999999,
663   "label": {
664     "Name": "value",
665     "Value": 0
666   },
667   "float-max": 3.4028234663852886e+38,
668   "float-min": 1.1754943508222875e-38,
669   "float-inf": )" + formatJsonFloatString(InfFloat) +
670                                       R"(,
671   "float-nan": )" + formatJsonFloatString(NaNFloat) +
672                                       R"(,
673   "float-42.0": 42,
674   "float-42.5625": 42.5625,
675   "double-max": 1.7976931348623157e+308,
676   "double-min": 2.2250738585072014e-308,
677   "double-inf": )" + formatJsonFloatString(InfDouble) +
678                                       R"(,
679   "double-nan": )" + formatJsonFloatString(NaNDouble) +
680                                       R"(,
681   "double-42.0": 42,
682   "double-42.5625": 42.5625
683 })")
684                                     .str();
685   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
686 }
687 
688 TEST_F(ScopedPrinterTest, PrintBoolean) {
689   auto PrintFunc = [](ScopedPrinter &W) {
690     W.printBoolean("True", true);
691     W.printBoolean("False", false);
692   };
693 
694   const char *ExpectedOut = R"(True: Yes
695 False: No
696 )";
697 
698   const char *JSONExpectedOut = R"({
699   "True": true,
700   "False": false
701 })";
702   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
703 }
704 
705 TEST_F(ScopedPrinterTest, PrintVersion) {
706   auto PrintFunc = [](ScopedPrinter &W) {
707     W.printVersion("Version", "123", "456", "789");
708   };
709   const char *ExpectedOut = R"(Version: 123.456.789
710 )";
711   verifyScopedPrinter(ExpectedOut, PrintFunc);
712 }
713 
714 TEST_F(ScopedPrinterTest, PrintList) {
715   auto PrintFunc = [](ScopedPrinter &W) {
716     const std::vector<uint64_t> EmptyList;
717     const std::vector<std::string> StringList = {"foo", "bar", "baz"};
718     const bool BoolList[] = {true, false};
719     const std::vector<uint64_t> Unsigned64List = {
720         std::numeric_limits<uint64_t>::max(),
721         std::numeric_limits<uint64_t>::min()};
722     const std::vector<uint32_t> Unsigned32List = {
723         std::numeric_limits<uint32_t>::max(),
724         std::numeric_limits<uint32_t>::min()};
725     const std::vector<uint16_t> Unsigned16List = {
726         std::numeric_limits<uint16_t>::max(),
727         std::numeric_limits<uint16_t>::min()};
728     const std::vector<uint8_t> Unsigned8List = {
729         std::numeric_limits<uint8_t>::max(),
730         std::numeric_limits<uint8_t>::min()};
731     const std::vector<int64_t> Signed64List = {
732         std::numeric_limits<int64_t>::max(),
733         std::numeric_limits<int64_t>::min()};
734     const std::vector<int32_t> Signed32List = {
735         std::numeric_limits<int32_t>::max(),
736         std::numeric_limits<int32_t>::min()};
737     const std::vector<int16_t> Signed16List = {
738         std::numeric_limits<int16_t>::max(),
739         std::numeric_limits<int16_t>::min()};
740     const std::vector<int8_t> Signed8List = {
741         std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min()};
742     const std::vector<APSInt> APSIntList = {APSInt("9999999999999999999999"),
743                                             APSInt("-9999999999999999999999")};
744     W.printList("EmptyList", EmptyList);
745     W.printList("StringList", StringList);
746     W.printList("BoolList", ArrayRef(BoolList));
747     W.printList("uint64List", Unsigned64List);
748     W.printList("uint32List", Unsigned32List);
749     W.printList("uint16List", Unsigned16List);
750     W.printList("uint8List", Unsigned8List);
751     W.printList("int64List", Signed64List);
752     W.printList("int32List", Signed32List);
753     W.printList("int16List", Signed16List);
754     W.printList("int8List", Signed8List);
755     W.printList("APSIntList", APSIntList);
756   };
757 
758   const char *ExpectedOut = R"(EmptyList: []
759 StringList: [foo, bar, baz]
760 BoolList: [1, 0]
761 uint64List: [18446744073709551615, 0]
762 uint32List: [4294967295, 0]
763 uint16List: [65535, 0]
764 uint8List: [255, 0]
765 int64List: [9223372036854775807, -9223372036854775808]
766 int32List: [2147483647, -2147483648]
767 int16List: [32767, -32768]
768 int8List: [127, -128]
769 APSIntList: [9999999999999999999999, -9999999999999999999999]
770 )";
771 
772   const char *JSONExpectedOut = R"({
773   "EmptyList": [],
774   "StringList": [
775     "foo",
776     "bar",
777     "baz"
778   ],
779   "BoolList": [
780     true,
781     false
782   ],
783   "uint64List": [
784     18446744073709551615,
785     0
786   ],
787   "uint32List": [
788     4294967295,
789     0
790   ],
791   "uint16List": [
792     65535,
793     0
794   ],
795   "uint8List": [
796     255,
797     0
798   ],
799   "int64List": [
800     9223372036854775807,
801     -9223372036854775808
802   ],
803   "int32List": [
804     2147483647,
805     -2147483648
806   ],
807   "int16List": [
808     32767,
809     -32768
810   ],
811   "int8List": [
812     127,
813     -128
814   ],
815   "APSIntList": [
816     9999999999999999999999,
817     -9999999999999999999999
818   ]
819 })";
820   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
821 }
822 
823 TEST_F(ScopedPrinterTest, PrintListPrinter) {
824   auto PrintFunc = [](ScopedPrinter &W) {
825     const std::string StringList[] = {"a", "ab", "abc"};
826     W.printList("StringSizeList", StringList,
827                 [](raw_ostream &OS, StringRef Item) { OS << Item.size(); });
828   };
829 
830   const char *ExpectedOut = R"(StringSizeList: [1, 2, 3]
831 )";
832   verifyScopedPrinter(ExpectedOut, PrintFunc);
833 }
834 
835 TEST_F(ScopedPrinterTest, PrintHex) {
836   auto PrintFunc = [](ScopedPrinter &W) {
837     W.printHex("HexNumber", 0x10);
838     W.printHex("HexLabel", "Name", 0x10);
839   };
840 
841   const char *ExpectedOut = R"(HexNumber: 0x10
842 HexLabel: Name (0x10)
843 )";
844 
845   const char *JSONExpectedOut = R"({
846   "HexNumber": 16,
847   "HexLabel": {
848     "Name": "Name",
849     "Value": 16
850   }
851 })";
852   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
853 }
854 
855 TEST_F(ScopedPrinterTest, PrintHexList) {
856   auto PrintFunc = [](ScopedPrinter &W) {
857     const uint64_t HexList[] = {0x1, 0x10, 0x100};
858     W.printHexList("HexList", HexList);
859   };
860   const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100]
861 )";
862 
863   const char *JSONExpectedOut = R"({
864   "HexList": [
865     1,
866     16,
867     256
868   ]
869 })";
870   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
871 }
872 
873 TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
874   auto PrintFunc = [](ScopedPrinter &W) {
875     W.printSymbolOffset("SymbolOffset", "SymbolName", 0x10);
876     W.printSymbolOffset("NoSymbolOffset", "SymbolName", 0);
877   };
878   const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10
879 NoSymbolOffset: SymbolName+0x0
880 )";
881 
882   const char *JSONExpectedOut = R"({
883   "SymbolOffset": {
884     "SymName": "SymbolName",
885     "Offset": 16
886   },
887   "NoSymbolOffset": {
888     "SymName": "SymbolName",
889     "Offset": 0
890   }
891 })";
892   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
893 }
894 
895 TEST_F(ScopedPrinterTest, PrintString) {
896   auto PrintFunc = [](ScopedPrinter &W) {
897     const StringRef StringRefValue("Value");
898     const std::string StringValue = "Value";
899     const char *CharArrayValue = "Value";
900     W.printString("StringRef", StringRefValue);
901     W.printString("String", StringValue);
902     W.printString("CharArray", CharArrayValue);
903     ListScope L(W, "StringList");
904     W.printString(StringRefValue);
905   };
906 
907   const char *ExpectedOut = R"(StringRef: Value
908 String: Value
909 CharArray: Value
910 StringList [
911   Value
912 ]
913 )";
914 
915   const char *JSONExpectedOut = R"({
916   "StringRef": "Value",
917   "String": "Value",
918   "CharArray": "Value",
919   "StringList": [
920     "Value"
921   ]
922 })";
923   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
924 }
925 
926 TEST_F(ScopedPrinterTest, PrintBinary) {
927   auto PrintFunc = [](ScopedPrinter &W) {
928     std::vector<uint8_t> IntArray = {70, 111, 111, 66, 97, 114};
929     std::vector<char> CharArray = {'F', 'o', 'o', 'B', 'a', 'r'};
930     std::vector<uint8_t> InvalidChars = {255, 255};
931     W.printBinary("Binary1", "FooBar", IntArray);
932     W.printBinary("Binary2", "FooBar", CharArray);
933     W.printBinary("Binary3", IntArray);
934     W.printBinary("Binary4", CharArray);
935     W.printBinary("Binary5", StringRef("FooBar"));
936     W.printBinary("Binary6", StringRef("Multiple Line FooBar"));
937     W.printBinaryBlock("Binary7", IntArray, 20);
938     W.printBinaryBlock("Binary8", IntArray);
939     W.printBinaryBlock("Binary9", "FooBar");
940     W.printBinaryBlock("Binary10", "Multiple Line FooBar");
941     W.printBinaryBlock("Binary11", InvalidChars);
942   };
943 
944   const char *ExpectedOut = R"(Binary1: FooBar (46 6F 6F 42 61 72)
945 Binary2: FooBar (46 6F 6F 42 61 72)
946 Binary3: (46 6F 6F 42 61 72)
947 Binary4: (46 6F 6F 42 61 72)
948 Binary5: (46 6F 6F 42 61 72)
949 Binary6 (
950   0000: 4D756C74 69706C65 204C696E 6520466F  |Multiple Line Fo|
951   0010: 6F426172                             |oBar|
952 )
953 Binary7 (
954   0014: 466F6F42 6172                        |FooBar|
955 )
956 Binary8 (
957   0000: 466F6F42 6172                        |FooBar|
958 )
959 Binary9 (
960   0000: 466F6F42 6172                        |FooBar|
961 )
962 Binary10 (
963   0000: 4D756C74 69706C65 204C696E 6520466F  |Multiple Line Fo|
964   0010: 6F426172                             |oBar|
965 )
966 Binary11 (
967   0000: FFFF                                 |..|
968 )
969 )";
970 
971   const char *JSONExpectedOut = R"({
972   "Binary1": {
973     "Value": "FooBar",
974     "Offset": 0,
975     "Bytes": [
976       70,
977       111,
978       111,
979       66,
980       97,
981       114
982     ]
983   },
984   "Binary2": {
985     "Value": "FooBar",
986     "Offset": 0,
987     "Bytes": [
988       70,
989       111,
990       111,
991       66,
992       97,
993       114
994     ]
995   },
996   "Binary3": {
997     "Offset": 0,
998     "Bytes": [
999       70,
1000       111,
1001       111,
1002       66,
1003       97,
1004       114
1005     ]
1006   },
1007   "Binary4": {
1008     "Offset": 0,
1009     "Bytes": [
1010       70,
1011       111,
1012       111,
1013       66,
1014       97,
1015       114
1016     ]
1017   },
1018   "Binary5": {
1019     "Offset": 0,
1020     "Bytes": [
1021       70,
1022       111,
1023       111,
1024       66,
1025       97,
1026       114
1027     ]
1028   },
1029   "Binary6": {
1030     "Offset": 0,
1031     "Bytes": [
1032       77,
1033       117,
1034       108,
1035       116,
1036       105,
1037       112,
1038       108,
1039       101,
1040       32,
1041       76,
1042       105,
1043       110,
1044       101,
1045       32,
1046       70,
1047       111,
1048       111,
1049       66,
1050       97,
1051       114
1052     ]
1053   },
1054   "Binary7": {
1055     "Offset": 20,
1056     "Bytes": [
1057       70,
1058       111,
1059       111,
1060       66,
1061       97,
1062       114
1063     ]
1064   },
1065   "Binary8": {
1066     "Offset": 0,
1067     "Bytes": [
1068       70,
1069       111,
1070       111,
1071       66,
1072       97,
1073       114
1074     ]
1075   },
1076   "Binary9": {
1077     "Offset": 0,
1078     "Bytes": [
1079       70,
1080       111,
1081       111,
1082       66,
1083       97,
1084       114
1085     ]
1086   },
1087   "Binary10": {
1088     "Offset": 0,
1089     "Bytes": [
1090       77,
1091       117,
1092       108,
1093       116,
1094       105,
1095       112,
1096       108,
1097       101,
1098       32,
1099       76,
1100       105,
1101       110,
1102       101,
1103       32,
1104       70,
1105       111,
1106       111,
1107       66,
1108       97,
1109       114
1110     ]
1111   },
1112   "Binary11": {
1113     "Offset": 0,
1114     "Bytes": [
1115       255,
1116       255
1117     ]
1118   }
1119 })";
1120   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
1121 }
1122 
1123 TEST_F(ScopedPrinterTest, PrintObject) {
1124   auto PrintFunc = [](ScopedPrinter &W) { W.printObject("Object", "Value"); };
1125 
1126   const char *ExpectedOut = R"(Object: Value
1127 )";
1128 
1129   const char *JSONExpectedOut = R"({
1130   "Object": "Value"
1131 })";
1132   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
1133 }
1134 
1135 TEST_F(ScopedPrinterTest, StartLine) {
1136   auto PrintFunc = [](ScopedPrinter &W) {
1137     W.startLine() << "|";
1138     W.indent(2);
1139     W.startLine() << "|";
1140     W.unindent();
1141     W.startLine() << "|";
1142   };
1143 
1144   const char *ExpectedOut = "|    |  |";
1145   verifyScopedPrinter(ExpectedOut, PrintFunc);
1146 }
1147 
1148 TEST_F(ScopedPrinterTest, GetOStream) {
1149   auto PrintFunc = [](ScopedPrinter &W) { W.getOStream() << "Test"; };
1150 
1151   const char *ExpectedOut = "Test";
1152   verifyScopedPrinter(ExpectedOut, PrintFunc);
1153 }
1154 
1155 TEST_F(ScopedPrinterTest, PrintScope) {
1156   auto PrintFunc = [](ScopedPrinter &W) {
1157     {
1158       DictScope O(W, "Object");
1159       { DictScope OO(W, "ObjectInObject"); }
1160       { ListScope LO(W, "ListInObject"); }
1161     }
1162     {
1163       ListScope L(W, "List");
1164       { DictScope OL(W, "ObjectInList"); }
1165       { ListScope LL(W, "ListInList"); }
1166     }
1167   };
1168 
1169   const char *ExpectedOut = R"(Object {
1170   ObjectInObject {
1171   }
1172   ListInObject [
1173   ]
1174 }
1175 List [
1176   ObjectInList {
1177   }
1178   ListInList [
1179   ]
1180 ]
1181 )";
1182 
1183   const char *JSONExpectedOut = R"({
1184   "Object": {
1185     "ObjectInObject": {},
1186     "ListInObject": []
1187   },
1188   "List": [
1189     {
1190       "ObjectInList": {}
1191     },
1192     {
1193       "ListInList": []
1194     }
1195   ]
1196 })";
1197   verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
1198 }
1199