blob: 895e04c2c024af3d79151e7fe24c0d299a0c7a65 [file] [log] [blame]
//===- llvm/unittest/Support/ScopedPrinterTest.cpp - ScopedPrinter tests --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/Support/Format.h"
#include "gtest/gtest.h"
#include <cmath>
#include <vector>
using namespace llvm;
TEST(JSONScopedPrinterTest, PrettyPrintCtor) {
auto PrintFunc = [](ScopedPrinter &W) {
DictScope D(W);
W.printString("Key", "Value");
};
std::string StreamBuffer;
raw_string_ostream OS(StreamBuffer);
JSONScopedPrinter PrettyPrintWriter(OS, /*PrettyPrint=*/true);
JSONScopedPrinter NoPrettyPrintWriter(OS, /*PrettyPrint=*/false);
const char *PrettyPrintOut = R"({
"Key": "Value"
})";
const char *NoPrettyPrintOut = R"({"Key":"Value"})";
PrintFunc(PrettyPrintWriter);
EXPECT_EQ(PrettyPrintOut, OS.str());
StreamBuffer.clear();
PrintFunc(NoPrettyPrintWriter);
EXPECT_EQ(NoPrettyPrintOut, OS.str());
}
TEST(JSONScopedPrinterTest, DelimitedScopeCtor) {
std::string StreamBuffer;
raw_string_ostream OS(StreamBuffer);
{
JSONScopedPrinter DictScopeWriter(OS, /*PrettyPrint=*/false,
std::make_unique<DictScope>());
DictScopeWriter.printString("Label", "DictScope");
}
EXPECT_EQ(R"({"Label":"DictScope"})", OS.str());
StreamBuffer.clear();
{
JSONScopedPrinter ListScopeWriter(OS, /*PrettyPrint=*/false,
std::make_unique<ListScope>());
ListScopeWriter.printString("ListScope");
}
EXPECT_EQ(R"(["ListScope"])", OS.str());
StreamBuffer.clear();
{
JSONScopedPrinter NoScopeWriter(OS, /*PrettyPrint=*/false);
NoScopeWriter.printString("NoScope");
}
EXPECT_EQ(R"("NoScope")", OS.str());
}
class ScopedPrinterTest : public ::testing::Test {
protected:
std::string StreamBuffer;
raw_string_ostream OS;
ScopedPrinter Writer;
JSONScopedPrinter JSONWriter;
bool HasPrintedToJSON;
ScopedPrinterTest()
: OS(StreamBuffer), Writer(OS), JSONWriter(OS, /*PrettyPrint=*/true),
HasPrintedToJSON(false) {}
using PrintFunc = function_ref<void(ScopedPrinter &)>;
void verifyScopedPrinter(StringRef Expected, PrintFunc Func) {
Func(Writer);
Writer.flush();
EXPECT_EQ(Expected.str(), OS.str());
StreamBuffer.clear();
}
void verifyJSONScopedPrinter(StringRef Expected, PrintFunc Func) {
{
DictScope D(JSONWriter);
Func(JSONWriter);
}
JSONWriter.flush();
EXPECT_EQ(Expected.str(), OS.str());
StreamBuffer.clear();
HasPrintedToJSON = true;
}
void verifyAll(StringRef ExpectedOut, StringRef JSONExpectedOut,
PrintFunc Func) {
verifyScopedPrinter(ExpectedOut, Func);
verifyJSONScopedPrinter(JSONExpectedOut, Func);
}
void TearDown() {
// JSONScopedPrinter fails an assert if nothing's been printed.
if (!HasPrintedToJSON)
JSONWriter.printString("");
}
};
TEST_F(ScopedPrinterTest, GetKind) {
EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::Base, Writer.getKind());
EXPECT_EQ(ScopedPrinter::ScopedPrinterKind::JSON, JSONWriter.getKind());
}
TEST_F(ScopedPrinterTest, ClassOf) {
EXPECT_TRUE(ScopedPrinter::classof(&Writer));
EXPECT_TRUE(JSONScopedPrinter::classof(&JSONWriter));
EXPECT_FALSE(ScopedPrinter::classof(&JSONWriter));
EXPECT_FALSE(JSONScopedPrinter::classof(&Writer));
}
TEST_F(ScopedPrinterTest, Indent) {
auto PrintFunc = [](ScopedPrinter &W) {
W.printString("|");
W.indent();
W.printString("|");
W.indent(2);
W.printString("|");
};
const char *ExpectedOut = R"(|
|
|
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, Unindent) {
auto PrintFunc = [](ScopedPrinter &W) {
W.indent(3);
W.printString("|");
W.unindent(2);
W.printString("|");
W.unindent();
W.printString("|");
W.unindent();
W.printString("|");
};
const char *ExpectedOut = R"( |
|
|
|
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, ResetIndent) {
auto PrintFunc = [](ScopedPrinter &W) {
W.indent(4);
W.printString("|");
W.resetIndent();
W.printString("|");
};
const char *ExpectedOut = R"( |
|
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintIndent) {
auto PrintFunc = [](ScopedPrinter &W) {
W.printIndent();
W.printString("|");
W.indent();
W.printIndent();
W.printString("|");
};
const char *ExpectedOut = R"(|
|
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, GetIndentLevel) {
EXPECT_EQ(Writer.getIndentLevel(), 0);
Writer.indent();
EXPECT_EQ(Writer.getIndentLevel(), 1);
Writer.indent();
EXPECT_EQ(Writer.getIndentLevel(), 2);
Writer.unindent();
EXPECT_EQ(Writer.getIndentLevel(), 1);
Writer.indent();
Writer.resetIndent();
EXPECT_EQ(Writer.getIndentLevel(), 0);
Writer.unindent();
EXPECT_EQ(Writer.getIndentLevel(), 0);
Writer.indent();
EXPECT_EQ(Writer.getIndentLevel(), 1);
}
TEST_F(ScopedPrinterTest, SetPrefix) {
auto PrintFunc = [](ScopedPrinter &W) {
W.setPrefix("Prefix1");
W.indent();
W.printIndent();
W.printString("|");
W.unindent();
W.printIndent();
W.printString("|");
W.setPrefix("Prefix2");
W.printIndent();
W.printString("|");
};
const char *ExpectedOut = R"(Prefix1 Prefix1 |
Prefix1Prefix1|
Prefix2Prefix2|
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintEnum) {
auto PrintFunc = [](ScopedPrinter &W) {
const EnumEntry<int> EnumList[] = {{"Name1", "AltName1", 1},
{"Name2", "AltName2", 2},
{"Name3", "AltName3", 3},
{"Name4", "AltName4", 2}};
EnumEntry<int> OtherEnum{"Name5", "AltName5", 5};
W.printEnum("Exists", EnumList[1].Value, ArrayRef(EnumList));
W.printEnum("DoesNotExist", OtherEnum.Value, ArrayRef(EnumList));
};
const char *ExpectedOut = R"(Exists: Name2 (0x2)
DoesNotExist: 0x5
)";
const char *JSONExpectedOut = R"({
"Exists": {
"Name": "Name2",
"Value": 2
},
"DoesNotExist": 5
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintFlag) {
auto PrintFunc = [](ScopedPrinter &W) {
const EnumEntry<uint16_t> SingleBitFlags[] = {
{"Name0", "AltName0", 0},
{"Name1", "AltName1", 1},
{"Name2", "AltName2", 1 << 1},
{"Name3", "AltName3", 1 << 2}};
const EnumEntry<uint16_t> UnsortedFlags[] = {
{"C", "c", 1}, {"B", "b", 1 << 1}, {"A", "a", 1 << 2}};
const EnumEntry<uint16_t> EnumFlags[] = {
{"FirstByte1", "First1", 0x1u}, {"FirstByte2", "First2", 0x2u},
{"FirstByte3", "First3", 0x3u}, {"SecondByte1", "Second1", 0x10u},
{"SecondByte2", "Second2", 0x20u}, {"SecondByte3", "Second3", 0x30u},
{"ThirdByte1", "Third1", 0x100u}, {"ThirdByte2", "Third2", 0x200u},
{"ThirdByte3", "Third3", 0x300u}};
W.printFlags("ZeroFlag", 0, ArrayRef(SingleBitFlags));
W.printFlags("NoFlag", 1 << 3, ArrayRef(SingleBitFlags));
W.printFlags("Flag1", SingleBitFlags[1].Value, ArrayRef(SingleBitFlags));
W.printFlags("Flag1&3", (1 << 2) + 1, ArrayRef(SingleBitFlags));
W.printFlags("ZeroFlagRaw", 0);
W.printFlags("NoFlagRaw", 1 << 3);
W.printFlags("Flag1Raw", SingleBitFlags[1].Value);
W.printFlags("Flag1&3Raw", (1 << 2) + 1);
W.printFlags("FlagSorted", (1 << 2) + (1 << 1) + 1,
ArrayRef(UnsortedFlags));
uint16_t NoBitMask = 0;
uint16_t FirstByteMask = 0xFu;
uint16_t SecondByteMask = 0xF0u;
uint16_t ThirdByteMask = 0xF00u;
W.printFlags("NoBitMask", 0xFFFu, ArrayRef(EnumFlags), NoBitMask);
W.printFlags("FirstByteMask", 0x3u, ArrayRef(EnumFlags), FirstByteMask);
W.printFlags("SecondByteMask", 0x30u, ArrayRef(EnumFlags), SecondByteMask);
W.printFlags("ValueOutsideMask", 0x1u, ArrayRef(EnumFlags), SecondByteMask);
W.printFlags("FirstSecondByteMask", 0xFFu, ArrayRef(EnumFlags),
FirstByteMask, SecondByteMask);
W.printFlags("FirstSecondThirdByteMask", 0x333u, ArrayRef(EnumFlags),
FirstByteMask, SecondByteMask, ThirdByteMask);
};
const char *ExpectedOut = R"(ZeroFlag [ (0x0)
]
NoFlag [ (0x8)
]
Flag1 [ (0x1)
Name1 (0x1)
]
Flag1&3 [ (0x5)
Name1 (0x1)
Name3 (0x4)
]
ZeroFlagRaw [ (0x0)
]
NoFlagRaw [ (0x8)
0x8
]
Flag1Raw [ (0x1)
0x1
]
Flag1&3Raw [ (0x5)
0x1
0x4
]
FlagSorted [ (0x7)
A (0x4)
B (0x2)
C (0x1)
]
NoBitMask [ (0xFFF)
FirstByte1 (0x1)
FirstByte2 (0x2)
FirstByte3 (0x3)
SecondByte1 (0x10)
SecondByte2 (0x20)
SecondByte3 (0x30)
ThirdByte1 (0x100)
ThirdByte2 (0x200)
ThirdByte3 (0x300)
]
FirstByteMask [ (0x3)
FirstByte3 (0x3)
]
SecondByteMask [ (0x30)
SecondByte3 (0x30)
]
ValueOutsideMask [ (0x1)
FirstByte1 (0x1)
]
FirstSecondByteMask [ (0xFF)
]
FirstSecondThirdByteMask [ (0x333)
FirstByte3 (0x3)
SecondByte3 (0x30)
ThirdByte3 (0x300)
]
)";
const char *JSONExpectedOut = R"({
"ZeroFlag": {
"Value": 0,
"Flags": []
},
"NoFlag": {
"Value": 8,
"Flags": []
},
"Flag1": {
"Value": 1,
"Flags": [
{
"Name": "Name1",
"Value": 1
}
]
},
"Flag1&3": {
"Value": 5,
"Flags": [
{
"Name": "Name1",
"Value": 1
},
{
"Name": "Name3",
"Value": 4
}
]
},
"ZeroFlagRaw": {
"Value": 0,
"Flags": []
},
"NoFlagRaw": {
"Value": 8,
"Flags": [
8
]
},
"Flag1Raw": {
"Value": 1,
"Flags": [
1
]
},
"Flag1&3Raw": {
"Value": 5,
"Flags": [
1,
4
]
},
"FlagSorted": {
"Value": 7,
"Flags": [
{
"Name": "A",
"Value": 4
},
{
"Name": "B",
"Value": 2
},
{
"Name": "C",
"Value": 1
}
]
},
"NoBitMask": {
"Value": 4095,
"Flags": [
{
"Name": "FirstByte1",
"Value": 1
},
{
"Name": "FirstByte2",
"Value": 2
},
{
"Name": "FirstByte3",
"Value": 3
},
{
"Name": "SecondByte1",
"Value": 16
},
{
"Name": "SecondByte2",
"Value": 32
},
{
"Name": "SecondByte3",
"Value": 48
},
{
"Name": "ThirdByte1",
"Value": 256
},
{
"Name": "ThirdByte2",
"Value": 512
},
{
"Name": "ThirdByte3",
"Value": 768
}
]
},
"FirstByteMask": {
"Value": 3,
"Flags": [
{
"Name": "FirstByte3",
"Value": 3
}
]
},
"SecondByteMask": {
"Value": 48,
"Flags": [
{
"Name": "SecondByte3",
"Value": 48
}
]
},
"ValueOutsideMask": {
"Value": 1,
"Flags": [
{
"Name": "FirstByte1",
"Value": 1
}
]
},
"FirstSecondByteMask": {
"Value": 255,
"Flags": []
},
"FirstSecondThirdByteMask": {
"Value": 819,
"Flags": [
{
"Name": "FirstByte3",
"Value": 3
},
{
"Name": "SecondByte3",
"Value": 48
},
{
"Name": "ThirdByte3",
"Value": 768
}
]
}
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
// Format floats using the same format string as PrintNumber, so we can check
// the output on all platforms.
template <typename T,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
std::string formatFloatString(T Val) {
std::string Ret;
raw_string_ostream OS(Ret);
OS << format("%5.1f", Val);
return Ret;
}
// Format floats using the same format string used in JSON, so we can check the
// output on all platforms.
template <typename T,
std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
std::string formatJsonFloatString(T Val) {
std::string Ret;
raw_string_ostream OS(Ret);
OS << format("%.*g", std::numeric_limits<double>::max_digits10, Val);
return Ret;
}
TEST_F(ScopedPrinterTest, PrintNumber) {
constexpr float MaxFloat = std::numeric_limits<float>::max();
constexpr float MinFloat = std::numeric_limits<float>::min();
constexpr float InfFloat = std::numeric_limits<float>::infinity();
const float NaNFloat = std::nanf("1");
constexpr double MaxDouble = std::numeric_limits<double>::max();
constexpr double MinDouble = std::numeric_limits<double>::min();
constexpr double InfDouble = std::numeric_limits<double>::infinity();
const double NaNDouble = std::nan("1");
auto PrintFunc = [&](ScopedPrinter &W) {
uint64_t Unsigned64Max = std::numeric_limits<uint64_t>::max();
uint64_t Unsigned64Min = std::numeric_limits<uint64_t>::min();
W.printNumber("uint64_t-max", Unsigned64Max);
W.printNumber("uint64_t-min", Unsigned64Min);
uint32_t Unsigned32Max = std::numeric_limits<uint32_t>::max();
uint32_t Unsigned32Min = std::numeric_limits<uint32_t>::min();
W.printNumber("uint32_t-max", Unsigned32Max);
W.printNumber("uint32_t-min", Unsigned32Min);
uint16_t Unsigned16Max = std::numeric_limits<uint16_t>::max();
uint16_t Unsigned16Min = std::numeric_limits<uint16_t>::min();
W.printNumber("uint16_t-max", Unsigned16Max);
W.printNumber("uint16_t-min", Unsigned16Min);
uint8_t Unsigned8Max = std::numeric_limits<uint8_t>::max();
uint8_t Unsigned8Min = std::numeric_limits<uint8_t>::min();
W.printNumber("uint8_t-max", Unsigned8Max);
W.printNumber("uint8_t-min", Unsigned8Min);
int64_t Signed64Max = std::numeric_limits<int64_t>::max();
int64_t Signed64Min = std::numeric_limits<int64_t>::min();
W.printNumber("int64_t-max", Signed64Max);
W.printNumber("int64_t-min", Signed64Min);
int32_t Signed32Max = std::numeric_limits<int32_t>::max();
int32_t Signed32Min = std::numeric_limits<int32_t>::min();
W.printNumber("int32_t-max", Signed32Max);
W.printNumber("int32_t-min", Signed32Min);
int16_t Signed16Max = std::numeric_limits<int16_t>::max();
int16_t Signed16Min = std::numeric_limits<int16_t>::min();
W.printNumber("int16_t-max", Signed16Max);
W.printNumber("int16_t-min", Signed16Min);
int8_t Signed8Max = std::numeric_limits<int8_t>::max();
int8_t Signed8Min = std::numeric_limits<int8_t>::min();
W.printNumber("int8_t-max", Signed8Max);
W.printNumber("int8_t-min", Signed8Min);
APSInt LargeNum("9999999999999999999999");
W.printNumber("apsint", LargeNum);
W.printNumber("label", "value", 0);
W.printNumber("float-max", MaxFloat);
W.printNumber("float-min", MinFloat);
W.printNumber("float-inf", InfFloat);
W.printNumber("float-nan", NaNFloat);
W.printNumber("float-42.0", 42.0f);
W.printNumber("float-42.5625", 42.5625f);
W.printNumber("double-max", MaxDouble);
W.printNumber("double-min", MinDouble);
W.printNumber("double-inf", InfDouble);
W.printNumber("double-nan", NaNDouble);
W.printNumber("double-42.0", 42.0);
W.printNumber("double-42.5625", 42.5625);
};
std::string ExpectedOut = Twine(
R"(uint64_t-max: 18446744073709551615
uint64_t-min: 0
uint32_t-max: 4294967295
uint32_t-min: 0
uint16_t-max: 65535
uint16_t-min: 0
uint8_t-max: 255
uint8_t-min: 0
int64_t-max: 9223372036854775807
int64_t-min: -9223372036854775808
int32_t-max: 2147483647
int32_t-min: -2147483648
int16_t-max: 32767
int16_t-min: -32768
int8_t-max: 127
int8_t-min: -128
apsint: 9999999999999999999999
label: value (0)
float-max: )" + formatFloatString(MaxFloat) +
R"(
float-min: 0.0
float-inf: )" + formatFloatString(InfFloat) +
R"(
float-nan: )" + formatFloatString(NaNFloat) +
R"(
float-42.0: 42.0
float-42.5625: 42.6
double-max: )" + formatFloatString(MaxDouble) +
R"(
double-min: 0.0
double-inf: )" + formatFloatString(InfDouble) +
R"(
double-nan: )" + formatFloatString(NaNDouble) +
R"(
double-42.0: 42.0
double-42.5625: 42.6
)")
.str();
std::string JSONExpectedOut = Twine(R"({
"uint64_t-max": 18446744073709551615,
"uint64_t-min": 0,
"uint32_t-max": 4294967295,
"uint32_t-min": 0,
"uint16_t-max": 65535,
"uint16_t-min": 0,
"uint8_t-max": 255,
"uint8_t-min": 0,
"int64_t-max": 9223372036854775807,
"int64_t-min": -9223372036854775808,
"int32_t-max": 2147483647,
"int32_t-min": -2147483648,
"int16_t-max": 32767,
"int16_t-min": -32768,
"int8_t-max": 127,
"int8_t-min": -128,
"apsint": 9999999999999999999999,
"label": {
"Name": "value",
"Value": 0
},
"float-max": 3.4028234663852886e+38,
"float-min": 1.1754943508222875e-38,
"float-inf": )" + formatJsonFloatString(InfFloat) +
R"(,
"float-nan": )" + formatJsonFloatString(NaNFloat) +
R"(,
"float-42.0": 42,
"float-42.5625": 42.5625,
"double-max": 1.7976931348623157e+308,
"double-min": 2.2250738585072014e-308,
"double-inf": )" + formatJsonFloatString(InfDouble) +
R"(,
"double-nan": )" + formatJsonFloatString(NaNDouble) +
R"(,
"double-42.0": 42,
"double-42.5625": 42.5625
})")
.str();
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintBoolean) {
auto PrintFunc = [](ScopedPrinter &W) {
W.printBoolean("True", true);
W.printBoolean("False", false);
};
const char *ExpectedOut = R"(True: Yes
False: No
)";
const char *JSONExpectedOut = R"({
"True": true,
"False": false
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintVersion) {
auto PrintFunc = [](ScopedPrinter &W) {
W.printVersion("Version", "123", "456", "789");
};
const char *ExpectedOut = R"(Version: 123.456.789
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintList) {
auto PrintFunc = [](ScopedPrinter &W) {
const std::vector<uint64_t> EmptyList;
const std::vector<std::string> StringList = {"foo", "bar", "baz"};
const bool BoolList[] = {true, false};
const std::vector<uint64_t> Unsigned64List = {
std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::min()};
const std::vector<uint32_t> Unsigned32List = {
std::numeric_limits<uint32_t>::max(),
std::numeric_limits<uint32_t>::min()};
const std::vector<uint16_t> Unsigned16List = {
std::numeric_limits<uint16_t>::max(),
std::numeric_limits<uint16_t>::min()};
const std::vector<uint8_t> Unsigned8List = {
std::numeric_limits<uint8_t>::max(),
std::numeric_limits<uint8_t>::min()};
const std::vector<int64_t> Signed64List = {
std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::min()};
const std::vector<int32_t> Signed32List = {
std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::min()};
const std::vector<int16_t> Signed16List = {
std::numeric_limits<int16_t>::max(),
std::numeric_limits<int16_t>::min()};
const std::vector<int8_t> Signed8List = {
std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min()};
const std::vector<APSInt> APSIntList = {APSInt("9999999999999999999999"),
APSInt("-9999999999999999999999")};
W.printList("EmptyList", EmptyList);
W.printList("StringList", StringList);
W.printList("BoolList", ArrayRef(BoolList));
W.printList("uint64List", Unsigned64List);
W.printList("uint32List", Unsigned32List);
W.printList("uint16List", Unsigned16List);
W.printList("uint8List", Unsigned8List);
W.printList("int64List", Signed64List);
W.printList("int32List", Signed32List);
W.printList("int16List", Signed16List);
W.printList("int8List", Signed8List);
W.printList("APSIntList", APSIntList);
};
const char *ExpectedOut = R"(EmptyList: []
StringList: [foo, bar, baz]
BoolList: [1, 0]
uint64List: [18446744073709551615, 0]
uint32List: [4294967295, 0]
uint16List: [65535, 0]
uint8List: [255, 0]
int64List: [9223372036854775807, -9223372036854775808]
int32List: [2147483647, -2147483648]
int16List: [32767, -32768]
int8List: [127, -128]
APSIntList: [9999999999999999999999, -9999999999999999999999]
)";
const char *JSONExpectedOut = R"({
"EmptyList": [],
"StringList": [
"foo",
"bar",
"baz"
],
"BoolList": [
true,
false
],
"uint64List": [
18446744073709551615,
0
],
"uint32List": [
4294967295,
0
],
"uint16List": [
65535,
0
],
"uint8List": [
255,
0
],
"int64List": [
9223372036854775807,
-9223372036854775808
],
"int32List": [
2147483647,
-2147483648
],
"int16List": [
32767,
-32768
],
"int8List": [
127,
-128
],
"APSIntList": [
9999999999999999999999,
-9999999999999999999999
]
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintListPrinter) {
auto PrintFunc = [](ScopedPrinter &W) {
const std::string StringList[] = {"a", "ab", "abc"};
W.printList("StringSizeList", StringList,
[](raw_ostream &OS, StringRef Item) { OS << Item.size(); });
};
const char *ExpectedOut = R"(StringSizeList: [1, 2, 3]
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintHex) {
auto PrintFunc = [](ScopedPrinter &W) {
W.printHex("HexNumber", 0x10);
W.printHex("HexLabel", "Name", 0x10);
};
const char *ExpectedOut = R"(HexNumber: 0x10
HexLabel: Name (0x10)
)";
const char *JSONExpectedOut = R"({
"HexNumber": 16,
"HexLabel": {
"Name": "Name",
"Value": 16
}
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintHexList) {
auto PrintFunc = [](ScopedPrinter &W) {
const uint64_t HexList[] = {0x1, 0x10, 0x100};
W.printHexList("HexList", HexList);
};
const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100]
)";
const char *JSONExpectedOut = R"({
"HexList": [
1,
16,
256
]
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
auto PrintFunc = [](ScopedPrinter &W) {
W.printSymbolOffset("SymbolOffset", "SymbolName", 0x10);
W.printSymbolOffset("NoSymbolOffset", "SymbolName", 0);
};
const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10
NoSymbolOffset: SymbolName+0x0
)";
const char *JSONExpectedOut = R"({
"SymbolOffset": {
"SymName": "SymbolName",
"Offset": 16
},
"NoSymbolOffset": {
"SymName": "SymbolName",
"Offset": 0
}
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintString) {
auto PrintFunc = [](ScopedPrinter &W) {
const StringRef StringRefValue("Value");
const std::string StringValue = "Value";
const char *CharArrayValue = "Value";
W.printString("StringRef", StringRefValue);
W.printString("String", StringValue);
W.printString("CharArray", CharArrayValue);
ListScope L(W, "StringList");
W.printString(StringRefValue);
};
const char *ExpectedOut = R"(StringRef: Value
String: Value
CharArray: Value
StringList [
Value
]
)";
const char *JSONExpectedOut = R"({
"StringRef": "Value",
"String": "Value",
"CharArray": "Value",
"StringList": [
"Value"
]
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintBinary) {
auto PrintFunc = [](ScopedPrinter &W) {
std::vector<uint8_t> IntArray = {70, 111, 111, 66, 97, 114};
std::vector<char> CharArray = {'F', 'o', 'o', 'B', 'a', 'r'};
std::vector<uint8_t> InvalidChars = {255, 255};
W.printBinary("Binary1", "FooBar", IntArray);
W.printBinary("Binary2", "FooBar", CharArray);
W.printBinary("Binary3", IntArray);
W.printBinary("Binary4", CharArray);
W.printBinary("Binary5", StringRef("FooBar"));
W.printBinary("Binary6", StringRef("Multiple Line FooBar"));
W.printBinaryBlock("Binary7", IntArray, 20);
W.printBinaryBlock("Binary8", IntArray);
W.printBinaryBlock("Binary9", "FooBar");
W.printBinaryBlock("Binary10", "Multiple Line FooBar");
W.printBinaryBlock("Binary11", InvalidChars);
};
const char *ExpectedOut = R"(Binary1: FooBar (46 6F 6F 42 61 72)
Binary2: FooBar (46 6F 6F 42 61 72)
Binary3: (46 6F 6F 42 61 72)
Binary4: (46 6F 6F 42 61 72)
Binary5: (46 6F 6F 42 61 72)
Binary6 (
0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo|
0010: 6F426172 |oBar|
)
Binary7 (
0014: 466F6F42 6172 |FooBar|
)
Binary8 (
0000: 466F6F42 6172 |FooBar|
)
Binary9 (
0000: 466F6F42 6172 |FooBar|
)
Binary10 (
0000: 4D756C74 69706C65 204C696E 6520466F |Multiple Line Fo|
0010: 6F426172 |oBar|
)
Binary11 (
0000: FFFF |..|
)
)";
const char *JSONExpectedOut = R"({
"Binary1": {
"Value": "FooBar",
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary2": {
"Value": "FooBar",
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary3": {
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary4": {
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary5": {
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary6": {
"Offset": 0,
"Bytes": [
77,
117,
108,
116,
105,
112,
108,
101,
32,
76,
105,
110,
101,
32,
70,
111,
111,
66,
97,
114
]
},
"Binary7": {
"Offset": 20,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary8": {
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary9": {
"Offset": 0,
"Bytes": [
70,
111,
111,
66,
97,
114
]
},
"Binary10": {
"Offset": 0,
"Bytes": [
77,
117,
108,
116,
105,
112,
108,
101,
32,
76,
105,
110,
101,
32,
70,
111,
111,
66,
97,
114
]
},
"Binary11": {
"Offset": 0,
"Bytes": [
255,
255
]
}
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintObject) {
auto PrintFunc = [](ScopedPrinter &W) { W.printObject("Object", "Value"); };
const char *ExpectedOut = R"(Object: Value
)";
const char *JSONExpectedOut = R"({
"Object": "Value"
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, StartLine) {
auto PrintFunc = [](ScopedPrinter &W) {
W.startLine() << "|";
W.indent(2);
W.startLine() << "|";
W.unindent();
W.startLine() << "|";
};
const char *ExpectedOut = "| | |";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, GetOStream) {
auto PrintFunc = [](ScopedPrinter &W) { W.getOStream() << "Test"; };
const char *ExpectedOut = "Test";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintScope) {
auto PrintFunc = [](ScopedPrinter &W) {
{
DictScope O(W, "Object");
{ DictScope OO(W, "ObjectInObject"); }
{ ListScope LO(W, "ListInObject"); }
}
{
ListScope L(W, "List");
{ DictScope OL(W, "ObjectInList"); }
{ ListScope LL(W, "ListInList"); }
}
};
const char *ExpectedOut = R"(Object {
ObjectInObject {
}
ListInObject [
]
}
List [
ObjectInList {
}
ListInList [
]
]
)";
const char *JSONExpectedOut = R"({
"Object": {
"ObjectInObject": {},
"ListInObject": []
},
"List": [
{
"ObjectInList": {}
},
{
"ListInList": []
}
]
})";
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
}