[llvm] Add ScopedPrinter unit tests

Add unit tests for the ScopedPrinter class.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D114684
This commit is contained in:
Jayson Yan 2021-12-10 18:35:11 +00:00
parent 80a0ee6f64
commit d25a65030b
2 changed files with 579 additions and 0 deletions

View File

@ -68,6 +68,7 @@ add_llvm_unittest(SupportTests
ReplaceFileTest.cpp
RISCVAttributeParserTest.cpp
ScaledNumberTest.cpp
ScopedPrinterTest.cpp
SHA256.cpp
SourceMgrTest.cpp
SpecialCaseListTest.cpp

View File

@ -0,0 +1,578 @@
//===- 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 "gtest/gtest.h"
#include <vector>
using namespace llvm;
class ScopedPrinterTest : public ::testing::Test {
protected:
std::string StreamBuffer;
raw_string_ostream OS;
ScopedPrinter Writer;
ScopedPrinterTest() : OS(StreamBuffer), Writer(OS) {}
using PrintFunc = function_ref<void(ScopedPrinter &)>;
void verifyScopedPrinter(StringRef Expected, PrintFunc Func) {
Func(Writer);
Writer.flush();
EXPECT_EQ(Expected.str(), OS.str());
}
};
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, makeArrayRef(EnumList));
W.printEnum("DoesNotExist", OtherEnum.Value, makeArrayRef(EnumList));
};
const char *ExpectedOut = R"(Exists: Name2 (0x2)
DoesNotExist: 0x5
)";
verifyScopedPrinter(ExpectedOut, 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, makeArrayRef(SingleBitFlags));
W.printFlags("NoFlag", 1 << 3, makeArrayRef(SingleBitFlags));
W.printFlags("Flag1", SingleBitFlags[1].Value,
makeArrayRef(SingleBitFlags));
W.printFlags("Flag1&3", (1 << 2) + 1, makeArrayRef(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,
makeArrayRef(UnsortedFlags));
uint16_t NoBitMask = 0;
uint16_t FirstByteMask = 0xFu;
uint16_t SecondByteMask = 0xF0u;
uint16_t ThirdByteMask = 0xF00u;
W.printFlags("NoBitMask", 0xFFFu, makeArrayRef(EnumFlags), NoBitMask);
W.printFlags("FirstByteMask", 0x3u, makeArrayRef(EnumFlags), FirstByteMask);
W.printFlags("SecondByteMask", 0x30u, makeArrayRef(EnumFlags),
SecondByteMask);
W.printFlags("ValueOutsideMask", 0x1u, makeArrayRef(EnumFlags),
SecondByteMask);
W.printFlags("FirstSecondByteMask", 0xFFu, makeArrayRef(EnumFlags),
FirstByteMask, SecondByteMask);
W.printFlags("FirstSecondThirdByteMask", 0x333u, makeArrayRef(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)
]
)";
verifyScopedPrinter(ExpectedOut, 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);
};
const char *ExpectedOut = 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)
)";
verifyScopedPrinter(ExpectedOut, 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
)";
verifyScopedPrinter(ExpectedOut, 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", makeArrayRef(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]
)";
verifyScopedPrinter(ExpectedOut, 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)
)";
verifyScopedPrinter(ExpectedOut, 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]
)";
verifyScopedPrinter(ExpectedOut, 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
)";
verifyScopedPrinter(ExpectedOut, 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
]
)";
verifyScopedPrinter(ExpectedOut, 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 |..|
)
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}
TEST_F(ScopedPrinterTest, PrintObject) {
auto PrintFunc = [](ScopedPrinter &W) { W.printObject("Object", "Value"); };
const char *ExpectedOut = R"(Object: Value
)";
verifyScopedPrinter(ExpectedOut, 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 [
]
]
)";
verifyScopedPrinter(ExpectedOut, PrintFunc);
}