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
16using namespace llvm;
17
18TEST(JSONScopedPrinterTest, PrettyPrintCtor) {
19 auto PrintFunc = [](ScopedPrinter &W) {
20 DictScope D(W);
21 W.printString(Label: "Key", Value: "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
39TEST(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: "Label", Value: "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(Value: "ListScope");
53 }
54 EXPECT_EQ(R"(["ListScope"])", OS.str());
55 StreamBuffer.clear();
56 {
57 JSONScopedPrinter NoScopeWriter(OS, /*PrettyPrint=*/false);
58 NoScopeWriter.printString(Value: "NoScope");
59 }
60 EXPECT_EQ(R"("NoScope")", OS.str());
61}
62
63class ScopedPrinterTest : public ::testing::Test {
64protected:
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(Expected: ExpectedOut, Func);
99 verifyJSONScopedPrinter(Expected: JSONExpectedOut, Func);
100 }
101
102 void TearDown() {
103 // JSONScopedPrinter fails an assert if nothing's been printed.
104 if (!HasPrintedToJSON)
105 JSONWriter.printString(Value: "");
106 }
107};
108
109TEST_F(ScopedPrinterTest, GetKind) {
110 EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::Base, Writer.getKind());
111 EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::JSON, JSONWriter.getKind());
112}
113
114TEST_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
121TEST_F(ScopedPrinterTest, Indent) {
122 auto PrintFunc = [](ScopedPrinter &W) {
123 W.printString(Value: "|");
124 W.indent();
125 W.printString(Value: "|");
126 W.indent(Levels: 2);
127 W.printString(Value: "|");
128 };
129
130 const char *ExpectedOut = R"(|
131 |
132 |
133)";
134 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
135}
136
137TEST_F(ScopedPrinterTest, Unindent) {
138 auto PrintFunc = [](ScopedPrinter &W) {
139 W.indent(Levels: 3);
140 W.printString(Value: "|");
141 W.unindent(Levels: 2);
142 W.printString(Value: "|");
143 W.unindent();
144 W.printString(Value: "|");
145 W.unindent();
146 W.printString(Value: "|");
147 };
148
149 const char *ExpectedOut = R"( |
150 |
151|
152|
153)";
154 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
155}
156
157TEST_F(ScopedPrinterTest, ResetIndent) {
158 auto PrintFunc = [](ScopedPrinter &W) {
159 W.indent(Levels: 4);
160 W.printString(Value: "|");
161 W.resetIndent();
162 W.printString(Value: "|");
163 };
164
165 const char *ExpectedOut = R"( |
166|
167)";
168 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
169}
170
171TEST_F(ScopedPrinterTest, PrintIndent) {
172 auto PrintFunc = [](ScopedPrinter &W) {
173 W.printIndent();
174 W.printString(Value: "|");
175 W.indent();
176 W.printIndent();
177 W.printString(Value: "|");
178 };
179
180 const char *ExpectedOut = R"(|
181 |
182)";
183 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
184}
185
186TEST_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
203TEST_F(ScopedPrinterTest, SetPrefix) {
204 auto PrintFunc = [](ScopedPrinter &W) {
205 W.setPrefix("Prefix1");
206 W.indent();
207 W.printIndent();
208 W.printString(Value: "|");
209 W.unindent();
210 W.printIndent();
211 W.printString(Value: "|");
212 W.setPrefix("Prefix2");
213 W.printIndent();
214 W.printString(Value: "|");
215 };
216
217 const char *ExpectedOut = R"(Prefix1 Prefix1 |
218Prefix1Prefix1|
219Prefix2Prefix2|
220)";
221 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
222}
223
224TEST_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(Label: "Exists", Value: EnumList[1].Value, EnumValues: ArrayRef(EnumList));
232 W.printEnum(Label: "DoesNotExist", Value: OtherEnum.Value, EnumValues: ArrayRef(EnumList));
233 };
234
235 const char *ExpectedOut = R"(Exists: Name2 (0x2)
236DoesNotExist: 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, Func: PrintFunc);
247}
248
249TEST_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(Label: "ZeroFlag", Value: 0, Flags: ArrayRef(SingleBitFlags));
265 W.printFlags(Label: "NoFlag", Value: 1 << 3, Flags: ArrayRef(SingleBitFlags));
266 W.printFlags(Label: "Flag1", Value: SingleBitFlags[1].Value, Flags: ArrayRef(SingleBitFlags));
267 W.printFlags(Label: "Flag1&3", Value: (1 << 2) + 1, Flags: ArrayRef(SingleBitFlags));
268
269 W.printFlags(Label: "ZeroFlagRaw", Value: 0);
270 W.printFlags(Label: "NoFlagRaw", Value: 1 << 3);
271 W.printFlags(Label: "Flag1Raw", Value: SingleBitFlags[1].Value);
272 W.printFlags(Label: "Flag1&3Raw", Value: (1 << 2) + 1);
273
274 W.printFlags(Label: "FlagSorted", Value: (1 << 2) + (1 << 1) + 1,
275 Flags: 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(Label: "NoBitMask", Value: 0xFFFu, Flags: ArrayRef(EnumFlags), EnumMask1: NoBitMask);
282 W.printFlags(Label: "FirstByteMask", Value: 0x3u, Flags: ArrayRef(EnumFlags), EnumMask1: FirstByteMask);
283 W.printFlags(Label: "SecondByteMask", Value: 0x30u, Flags: ArrayRef(EnumFlags), EnumMask1: SecondByteMask);
284 W.printFlags(Label: "ValueOutsideMask", Value: 0x1u, Flags: ArrayRef(EnumFlags), EnumMask1: SecondByteMask);
285 W.printFlags(Label: "FirstSecondByteMask", Value: 0xFFu, Flags: ArrayRef(EnumFlags),
286 EnumMask1: FirstByteMask, EnumMask2: SecondByteMask);
287 W.printFlags(Label: "FirstSecondThirdByteMask", Value: 0x333u, Flags: ArrayRef(EnumFlags),
288 EnumMask1: FirstByteMask, EnumMask2: SecondByteMask, EnumMask3: ThirdByteMask);
289 };
290
291 const char *ExpectedOut = R"(ZeroFlag [ (0x0)
292]
293NoFlag [ (0x8)
294]
295Flag1 [ (0x1)
296 Name1 (0x1)
297]
298Flag1&3 [ (0x5)
299 Name1 (0x1)
300 Name3 (0x4)
301]
302ZeroFlagRaw [ (0x0)
303]
304NoFlagRaw [ (0x8)
305 0x8
306]
307Flag1Raw [ (0x1)
308 0x1
309]
310Flag1&3Raw [ (0x5)
311 0x1
312 0x4
313]
314FlagSorted [ (0x7)
315 A (0x4)
316 B (0x2)
317 C (0x1)
318]
319NoBitMask [ (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]
330FirstByteMask [ (0x3)
331 FirstByte3 (0x3)
332]
333SecondByteMask [ (0x30)
334 SecondByte3 (0x30)
335]
336ValueOutsideMask [ (0x1)
337 FirstByte1 (0x1)
338]
339FirstSecondByteMask [ (0xFF)
340]
341FirstSecondThirdByteMask [ (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, Func: PrintFunc);
510}
511
512// Format floats using the same format string as PrintNumber, so we can check
513// the output on all platforms.
514template <typename T,
515 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
516std::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.
525template <typename T,
526 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
527std::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
534TEST_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(tagb: "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(tagb: "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(Label: "uint64_t-max", Value: Unsigned64Max);
548 W.printNumber(Label: "uint64_t-min", Value: 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(Label: "uint32_t-max", Value: Unsigned32Max);
553 W.printNumber(Label: "uint32_t-min", Value: 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(Label: "uint16_t-max", Value: Unsigned16Max);
558 W.printNumber(Label: "uint16_t-min", Value: 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(Label: "uint8_t-max", Value: Unsigned8Max);
563 W.printNumber(Label: "uint8_t-min", Value: 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(Label: "int64_t-max", Value: Signed64Max);
568 W.printNumber(Label: "int64_t-min", Value: 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(Label: "int32_t-max", Value: Signed32Max);
573 W.printNumber(Label: "int32_t-min", Value: 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(Label: "int16_t-max", Value: Signed16Max);
578 W.printNumber(Label: "int16_t-min", Value: 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(Label: "int8_t-max", Value: Signed8Max);
583 W.printNumber(Label: "int8_t-min", Value: Signed8Min);
584
585 APSInt LargeNum("9999999999999999999999");
586 W.printNumber(Label: "apsint", Value: LargeNum);
587
588 W.printNumber(Label: "label", Str: "value", Value: 0);
589
590 W.printNumber(Label: "float-max", Value: MaxFloat);
591 W.printNumber(Label: "float-min", Value: MinFloat);
592 W.printNumber(Label: "float-inf", Value: InfFloat);
593 W.printNumber(Label: "float-nan", Value: NaNFloat);
594 W.printNumber(Label: "float-42.0", Value: 42.0f);
595 W.printNumber(Label: "float-42.5625", Value: 42.5625f);
596
597 W.printNumber(Label: "double-max", Value: MaxDouble);
598 W.printNumber(Label: "double-min", Value: MinDouble);
599 W.printNumber(Label: "double-inf", Value: InfDouble);
600 W.printNumber(Label: "double-nan", Value: NaNDouble);
601 W.printNumber(Label: "double-42.0", Value: 42.0);
602 W.printNumber(Label: "double-42.5625", Value: 42.5625);
603 };
604
605 std::string ExpectedOut = Twine(
606 R"(uint64_t-max: 18446744073709551615
607uint64_t-min: 0
608uint32_t-max: 4294967295
609uint32_t-min: 0
610uint16_t-max: 65535
611uint16_t-min: 0
612uint8_t-max: 255
613uint8_t-min: 0
614int64_t-max: 9223372036854775807
615int64_t-min: -9223372036854775808
616int32_t-max: 2147483647
617int32_t-min: -2147483648
618int16_t-max: 32767
619int16_t-min: -32768
620int8_t-max: 127
621int8_t-min: -128
622apsint: 9999999999999999999999
623label: value (0)
624float-max: )" + formatFloatString(Val: MaxFloat) +
625 R"(
626float-min: 0.0
627float-inf: )" + formatFloatString(Val: InfFloat) +
628 R"(
629float-nan: )" + formatFloatString(Val: NaNFloat) +
630 R"(
631float-42.0: 42.0
632float-42.5625: 42.6
633double-max: )" + formatFloatString(Val: MaxDouble) +
634 R"(
635double-min: 0.0
636double-inf: )" + formatFloatString(Val: InfDouble) +
637 R"(
638double-nan: )" + formatFloatString(Val: NaNDouble) +
639 R"(
640double-42.0: 42.0
641double-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(Val: InfFloat) +
670 R"(,
671 "float-nan": )" + formatJsonFloatString(Val: 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(Val: InfDouble) +
678 R"(,
679 "double-nan": )" + formatJsonFloatString(Val: NaNDouble) +
680 R"(,
681 "double-42.0": 42,
682 "double-42.5625": 42.5625
683})")
684 .str();
685 verifyAll(ExpectedOut, JSONExpectedOut, Func: PrintFunc);
686}
687
688TEST_F(ScopedPrinterTest, PrintBoolean) {
689 auto PrintFunc = [](ScopedPrinter &W) {
690 W.printBoolean(Label: "True", Value: true);
691 W.printBoolean(Label: "False", Value: false);
692 };
693
694 const char *ExpectedOut = R"(True: Yes
695False: No
696)";
697
698 const char *JSONExpectedOut = R"({
699 "True": true,
700 "False": false
701})";
702 verifyAll(ExpectedOut, JSONExpectedOut, Func: PrintFunc);
703}
704
705TEST_F(ScopedPrinterTest, PrintVersion) {
706 auto PrintFunc = [](ScopedPrinter &W) {
707 W.printVersion(Label: "Version", Version: "123", Version: "456", Version: "789");
708 };
709 const char *ExpectedOut = R"(Version: 123.456.789
710)";
711 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
712}
713
714TEST_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(Label: "EmptyList", List: EmptyList);
745 W.printList(Label: "StringList", List: StringList);
746 W.printList(Label: "BoolList", List: ArrayRef(BoolList));
747 W.printList(Label: "uint64List", List: Unsigned64List);
748 W.printList(Label: "uint32List", List: Unsigned32List);
749 W.printList(Label: "uint16List", List: Unsigned16List);
750 W.printList(Label: "uint8List", List: Unsigned8List);
751 W.printList(Label: "int64List", List: Signed64List);
752 W.printList(Label: "int32List", List: Signed32List);
753 W.printList(Label: "int16List", List: Signed16List);
754 W.printList(Label: "int8List", List: Signed8List);
755 W.printList(Label: "APSIntList", List: APSIntList);
756 };
757
758 const char *ExpectedOut = R"(EmptyList: []
759StringList: [foo, bar, baz]
760BoolList: [1, 0]
761uint64List: [18446744073709551615, 0]
762uint32List: [4294967295, 0]
763uint16List: [65535, 0]
764uint8List: [255, 0]
765int64List: [9223372036854775807, -9223372036854775808]
766int32List: [2147483647, -2147483648]
767int16List: [32767, -32768]
768int8List: [127, -128]
769APSIntList: [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, Func: PrintFunc);
821}
822
823TEST_F(ScopedPrinterTest, PrintListPrinter) {
824 auto PrintFunc = [](ScopedPrinter &W) {
825 const std::string StringList[] = {"a", "ab", "abc"};
826 W.printList(Label: "StringSizeList", List: StringList,
827 Printer: [](raw_ostream &OS, StringRef Item) { OS << Item.size(); });
828 };
829
830 const char *ExpectedOut = R"(StringSizeList: [1, 2, 3]
831)";
832 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
833}
834
835TEST_F(ScopedPrinterTest, PrintHex) {
836 auto PrintFunc = [](ScopedPrinter &W) {
837 W.printHex(Label: "HexNumber", Value: 0x10);
838 W.printHex(Label: "HexLabel", Str: "Name", Value: 0x10);
839 };
840
841 const char *ExpectedOut = R"(HexNumber: 0x10
842HexLabel: 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, Func: PrintFunc);
853}
854
855TEST_F(ScopedPrinterTest, PrintHexList) {
856 auto PrintFunc = [](ScopedPrinter &W) {
857 const uint64_t HexList[] = {0x1, 0x10, 0x100};
858 W.printHexList(Label: "HexList", List: 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, Func: PrintFunc);
871}
872
873TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
874 auto PrintFunc = [](ScopedPrinter &W) {
875 W.printSymbolOffset(Label: "SymbolOffset", Symbol: "SymbolName", Value: 0x10);
876 W.printSymbolOffset(Label: "NoSymbolOffset", Symbol: "SymbolName", Value: 0);
877 };
878 const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10
879NoSymbolOffset: 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, Func: PrintFunc);
893}
894
895TEST_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(Label: "StringRef", Value: StringRefValue);
901 W.printString(Label: "String", Value: StringValue);
902 W.printString(Label: "CharArray", Value: CharArrayValue);
903 ListScope L(W, "StringList");
904 W.printString(Value: StringRefValue);
905 };
906
907 const char *ExpectedOut = R"(StringRef: Value
908String: Value
909CharArray: Value
910StringList [
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, Func: PrintFunc);
924}
925
926TEST_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(Label: "Binary1", Str: "FooBar", Value: IntArray);
932 W.printBinary(Label: "Binary2", Str: "FooBar", Value: CharArray);
933 W.printBinary(Label: "Binary3", Value: IntArray);
934 W.printBinary(Label: "Binary4", Value: CharArray);
935 W.printBinary(Label: "Binary5", Value: StringRef("FooBar"));
936 W.printBinary(Label: "Binary6", Value: StringRef("Multiple Line FooBar"));
937 W.printBinaryBlock(Label: "Binary7", Value: IntArray, StartOffset: 20);
938 W.printBinaryBlock(Label: "Binary8", Value: IntArray);
939 W.printBinaryBlock(Label: "Binary9", Value: "FooBar");
940 W.printBinaryBlock(Label: "Binary10", Value: "Multiple Line FooBar");
941 W.printBinaryBlock(Label: "Binary11", Value: InvalidChars);
942 };
943
944 const char *ExpectedOut = R"(Binary1: FooBar (46 6F 6F 42 61 72)
945Binary2: FooBar (46 6F 6F 42 61 72)
946Binary3: (46 6F 6F 42 61 72)
947Binary4: (46 6F 6F 42 61 72)
948Binary5: (46 6F 6F 42 61 72)
949Binary6 (
950 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo|
951 0010: 6F426172 |oBar|
952)
953Binary7 (
954 0014: 466F6F42 6172 |FooBar|
955)
956Binary8 (
957 0000: 466F6F42 6172 |FooBar|
958)
959Binary9 (
960 0000: 466F6F42 6172 |FooBar|
961)
962Binary10 (
963 0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo|
964 0010: 6F426172 |oBar|
965)
966Binary11 (
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, Func: PrintFunc);
1121}
1122
1123TEST_F(ScopedPrinterTest, PrintObject) {
1124 auto PrintFunc = [](ScopedPrinter &W) { W.printObject(Label: "Object", Value: "Value"); };
1125
1126 const char *ExpectedOut = R"(Object: Value
1127)";
1128
1129 const char *JSONExpectedOut = R"({
1130 "Object": "Value"
1131})";
1132 verifyAll(ExpectedOut, JSONExpectedOut, Func: PrintFunc);
1133}
1134
1135TEST_F(ScopedPrinterTest, StartLine) {
1136 auto PrintFunc = [](ScopedPrinter &W) {
1137 W.startLine() << "|";
1138 W.indent(Levels: 2);
1139 W.startLine() << "|";
1140 W.unindent();
1141 W.startLine() << "|";
1142 };
1143
1144 const char *ExpectedOut = "| | |";
1145 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
1146}
1147
1148TEST_F(ScopedPrinterTest, GetOStream) {
1149 auto PrintFunc = [](ScopedPrinter &W) { W.getOStream() << "Test"; };
1150
1151 const char *ExpectedOut = "Test";
1152 verifyScopedPrinter(Expected: ExpectedOut, Func: PrintFunc);
1153}
1154
1155TEST_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}
1175List [
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, Func: PrintFunc);
1198}
1199

source code of llvm/unittests/Support/ScopedPrinterTest.cpp