c819257b7f
The test strings we used for infinity and NAN were not correct on AIX. This patch creates those dynamically instead of hard-coded. Reviewed By: abhina.sreeskantharajan Differential Revision: https://reviews.llvm.org/D146542
1195 lines
28 KiB
C++
1195 lines
28 KiB
C++
//===- 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);
|
|
}
|
|
|
|
TEST_F(ScopedPrinterTest, PrintNumber) {
|
|
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);
|
|
|
|
float MaxFloat = std::numeric_limits<float>::max();
|
|
float MinFloat = std::numeric_limits<float>::min();
|
|
float InfFloat = std::numeric_limits<float>::infinity();
|
|
float NaNFloat = std::nanf("1");
|
|
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);
|
|
|
|
double MaxDouble = std::numeric_limits<double>::max();
|
|
double MinDouble = std::numeric_limits<double>::min();
|
|
double InfDouble = std::numeric_limits<double>::infinity();
|
|
double NaNDouble = std::nan("1");
|
|
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);
|
|
};
|
|
|
|
// Make sure when we check floating point representation we avoid
|
|
// implementation defined behavior. So format the max float/double, instead of
|
|
// hard coding it in the tests. Note: we can't just use std::to_string(),
|
|
// since we format the float in PrintNumber(). This isn't required for JSON
|
|
// formatting, since it uses exponents, which will be consistent.
|
|
|
|
// Allocate a buffer large enough to represent large floating point values
|
|
// and construct the string representation for them there.
|
|
char Buf[512];
|
|
|
|
format("%5.1f", std::numeric_limits<float>::max()).snprint(Buf, sizeof(Buf));
|
|
std::string MaxFloatStr(Buf);
|
|
|
|
format("%5.1f", std::numeric_limits<double>::max()).snprint(Buf, sizeof(Buf));
|
|
std::string MaxDoubleStr(Buf);
|
|
|
|
format("%5.1f", std::numeric_limits<double>::infinity())
|
|
.snprint(Buf, sizeof(Buf));
|
|
std::string InfFloatStr(Buf);
|
|
|
|
std::to_string(std::numeric_limits<float>::infinity());
|
|
std::string InfDoubleStr(Buf);
|
|
|
|
format("%5.1f", std::nanf("1")).snprint(Buf, sizeof(Buf));
|
|
std::string NaNFloatStr(Buf);
|
|
|
|
format("%5.1f", std::nan("1")).snprint(Buf, sizeof(Buf));
|
|
std::string NaNDoubleStr(Buf);
|
|
|
|
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: )" + MaxFloatStr + R"(
|
|
float-min: 0.0
|
|
float-inf: )" + InfFloatStr + R"(
|
|
float-nan: )" + NaNFloatStr + R"(
|
|
float-42.0: 42.0
|
|
float-42.5625: 42.6
|
|
double-max: )" + MaxDoubleStr +
|
|
R"(
|
|
double-min: 0.0
|
|
double-inf: )" + InfDoubleStr + R"(
|
|
double-nan: )" + NaNDoubleStr + R"(
|
|
double-42.0: 42.0
|
|
double-42.5625: 42.6
|
|
)")
|
|
.str();
|
|
|
|
const char *JSONExpectedOut = 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": inf,
|
|
"float-nan": nan,
|
|
"float-42.0": 42,
|
|
"float-42.5625": 42.5625,
|
|
"double-max": 1.7976931348623157e+308,
|
|
"double-min": 2.2250738585072014e-308,
|
|
"double-inf": inf,
|
|
"double-nan": nan,
|
|
"double-42.0": 42,
|
|
"double-42.5625": 42.5625
|
|
})";
|
|
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);
|
|
}
|