mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-30 11:36:08 +00:00

Previously there were several attempts to make the format checks for NaN and Inf work across platforms, like AIX and Solaris, that print these values slightly differently. This resulted in a number of forward fixes, until we finally disabled the tests for NaN and Inf. This change should make the test robust across different platforms, and reduce the overall amount of code by delegating to helper functions that use the same format strings as the implementations used by PrintNumber(). This additionally reverts commit 5a9bad171be5dfdf9430a0f6cbff14d29ca54181 and fa56e362af475e0758cfb41c42f78db50da7235c. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D146851
1199 lines
28 KiB
C++
1199 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);
|
|
}
|
|
|
|
// 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);
|
|
}
|