forked from OSchip/llvm-project
[llvm] Add JSONScopedPrinter class
This change adds a JSONScopedPrinter as a subclass to ScopedPrinter. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D114224
This commit is contained in:
parent
d25a65030b
commit
928d17254b
|
@ -16,6 +16,7 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/JSON.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -100,7 +101,20 @@ std::string enumToString(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) {
|
|||
|
||||
class ScopedPrinter {
|
||||
public:
|
||||
ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
|
||||
enum class ScopedPrinterKind {
|
||||
Base,
|
||||
JSON,
|
||||
};
|
||||
|
||||
ScopedPrinter(raw_ostream &OS,
|
||||
ScopedPrinterKind Kind = ScopedPrinterKind::Base)
|
||||
: OS(OS), IndentLevel(0), Kind(Kind) {}
|
||||
|
||||
ScopedPrinterKind getKind() const { return Kind; }
|
||||
|
||||
static bool classof(const ScopedPrinter *SP) {
|
||||
return SP->getKind() == ScopedPrinterKind::Base;
|
||||
}
|
||||
|
||||
virtual ~ScopedPrinter() {}
|
||||
|
||||
|
@ -487,6 +501,7 @@ private:
|
|||
raw_ostream &OS;
|
||||
int IndentLevel;
|
||||
StringRef Prefix;
|
||||
ScopedPrinterKind Kind;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@ -496,30 +511,329 @@ ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
|
|||
startLine() << Label << ": " << hex(Value) << "\n";
|
||||
}
|
||||
|
||||
struct DelimitedScope;
|
||||
|
||||
class JSONScopedPrinter : public ScopedPrinter {
|
||||
private:
|
||||
enum class Scope {
|
||||
Array,
|
||||
Object,
|
||||
};
|
||||
|
||||
enum class ScopeKind {
|
||||
NoAttribute,
|
||||
Attribute,
|
||||
NestedAttribute,
|
||||
};
|
||||
|
||||
struct ScopeContext {
|
||||
Scope Context;
|
||||
ScopeKind Kind;
|
||||
ScopeContext(Scope Context, ScopeKind Kind = ScopeKind::NoAttribute)
|
||||
: Context(Context), Kind(Kind) {}
|
||||
};
|
||||
|
||||
SmallVector<ScopeContext, 8> ScopeHistory;
|
||||
json::OStream JOS;
|
||||
std::unique_ptr<DelimitedScope> OuterScope;
|
||||
|
||||
public:
|
||||
JSONScopedPrinter(raw_ostream &OS, bool PrettyPrint = false,
|
||||
std::unique_ptr<DelimitedScope> &&OuterScope =
|
||||
std::unique_ptr<DelimitedScope>{});
|
||||
|
||||
static bool classof(const ScopedPrinter *SP) {
|
||||
return SP->getKind() == ScopedPrinter::ScopedPrinterKind::JSON;
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint64_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint32_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint16_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint8_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int64_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int32_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int16_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int8_t Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, const APSInt &Value) override {
|
||||
JOS.attributeBegin(Label);
|
||||
printAPSInt(Value);
|
||||
JOS.attributeEnd();
|
||||
}
|
||||
|
||||
void printBoolean(StringRef Label, bool Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<bool> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<std::string> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<uint64_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<uint32_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<uint16_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<uint8_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<int64_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<int32_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<int16_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<int8_t> List) override {
|
||||
printListImpl(Label, List);
|
||||
}
|
||||
|
||||
void printList(StringRef Label, const ArrayRef<APSInt> List) override {
|
||||
JOS.attributeArray(Label, [&]() {
|
||||
for (const APSInt &Item : List) {
|
||||
printAPSInt(Item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void printString(StringRef Value) override { JOS.value(Value); }
|
||||
|
||||
void printString(StringRef Label, StringRef Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void objectBegin() override {
|
||||
scopedBegin({Scope::Object, ScopeKind::NoAttribute});
|
||||
}
|
||||
|
||||
void objectBegin(StringRef Label) override {
|
||||
scopedBegin(Label, Scope::Object);
|
||||
}
|
||||
|
||||
void objectEnd() override { scopedEnd(); }
|
||||
|
||||
void arrayBegin() override {
|
||||
scopedBegin({Scope::Array, ScopeKind::NoAttribute});
|
||||
}
|
||||
|
||||
void arrayBegin(StringRef Label) override {
|
||||
scopedBegin(Label, Scope::Array);
|
||||
}
|
||||
|
||||
void arrayEnd() override { scopedEnd(); }
|
||||
|
||||
private:
|
||||
// Output HexNumbers as decimals so that they're easier to parse.
|
||||
uint64_t hexNumberToInt(HexNumber Hex) { return Hex.Value; }
|
||||
|
||||
void printAPSInt(const APSInt &Value) {
|
||||
JOS.rawValueBegin() << Value;
|
||||
JOS.rawValueEnd();
|
||||
}
|
||||
|
||||
void printFlagsImpl(StringRef Label, HexNumber Value,
|
||||
ArrayRef<FlagEntry> Flags) override {
|
||||
JOS.attributeObject(Label, [&]() {
|
||||
JOS.attribute("RawFlags", hexNumberToInt(Value));
|
||||
JOS.attributeArray("Flags", [&]() {
|
||||
for (const FlagEntry &Flag : Flags) {
|
||||
JOS.objectBegin();
|
||||
JOS.attribute("Name", Flag.Name);
|
||||
JOS.attribute("Value", Flag.Value);
|
||||
JOS.objectEnd();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void printFlagsImpl(StringRef Label, HexNumber Value,
|
||||
ArrayRef<HexNumber> Flags) override {
|
||||
JOS.attributeObject(Label, [&]() {
|
||||
JOS.attribute("RawFlags", hexNumberToInt(Value));
|
||||
JOS.attributeArray("Flags", [&]() {
|
||||
for (const HexNumber &Flag : Flags) {
|
||||
JOS.value(Flag.Value);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T> void printListImpl(StringRef Label, const T &List) {
|
||||
JOS.attributeArray(Label, [&]() {
|
||||
for (const auto &Item : List)
|
||||
JOS.value(Item);
|
||||
});
|
||||
}
|
||||
|
||||
void printHexListImpl(StringRef Label,
|
||||
const ArrayRef<HexNumber> List) override {
|
||||
JOS.attributeArray(Label, [&]() {
|
||||
for (const HexNumber &Item : List) {
|
||||
JOS.value(hexNumberToInt(Item));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void printHexImpl(StringRef Label, HexNumber Value) override {
|
||||
JOS.attribute(Label, hexNumberToInt(Value));
|
||||
}
|
||||
|
||||
void printHexImpl(StringRef Label, StringRef Str, HexNumber Value) override {
|
||||
JOS.attributeObject(Label, [&]() {
|
||||
JOS.attribute("Value", Str);
|
||||
JOS.attribute("RawValue", hexNumberToInt(Value));
|
||||
});
|
||||
}
|
||||
|
||||
void printSymbolOffsetImpl(StringRef Label, StringRef Symbol,
|
||||
HexNumber Value) override {
|
||||
JOS.attributeObject(Label, [&]() {
|
||||
JOS.attribute("SymName", Symbol);
|
||||
JOS.attribute("Offset", hexNumberToInt(Value));
|
||||
});
|
||||
}
|
||||
|
||||
void printNumberImpl(StringRef Label, StringRef Str,
|
||||
StringRef Value) override {
|
||||
JOS.attributeObject(Label, [&]() {
|
||||
JOS.attribute("Value", Str);
|
||||
JOS.attributeBegin("RawValue");
|
||||
JOS.rawValueBegin() << Value;
|
||||
JOS.rawValueEnd();
|
||||
JOS.attributeEnd();
|
||||
});
|
||||
}
|
||||
|
||||
void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
|
||||
bool Block, uint32_t StartOffset = 0) override {
|
||||
JOS.attributeObject(Label, [&]() {
|
||||
if (!Str.empty())
|
||||
JOS.attribute("Value", Str);
|
||||
JOS.attribute("Offset", StartOffset);
|
||||
JOS.attributeArray("Bytes", [&]() {
|
||||
for (uint8_t Val : Value)
|
||||
JOS.value(Val);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void scopedBegin(ScopeContext ScopeCtx) {
|
||||
if (ScopeCtx.Context == Scope::Object)
|
||||
JOS.objectBegin();
|
||||
else if (ScopeCtx.Context == Scope::Array)
|
||||
JOS.arrayBegin();
|
||||
ScopeHistory.push_back(ScopeCtx);
|
||||
}
|
||||
|
||||
void scopedBegin(StringRef Label, Scope Ctx) {
|
||||
ScopeKind Kind = ScopeKind::Attribute;
|
||||
if (ScopeHistory.empty() || ScopeHistory.back().Context != Scope::Object) {
|
||||
JOS.objectBegin();
|
||||
Kind = ScopeKind::NestedAttribute;
|
||||
}
|
||||
JOS.attributeBegin(Label);
|
||||
scopedBegin({Ctx, Kind});
|
||||
}
|
||||
|
||||
void scopedEnd() {
|
||||
ScopeContext ScopeCtx = ScopeHistory.back();
|
||||
if (ScopeCtx.Context == Scope::Object)
|
||||
JOS.objectEnd();
|
||||
else if (ScopeCtx.Context == Scope::Array)
|
||||
JOS.arrayEnd();
|
||||
if (ScopeCtx.Kind == ScopeKind::Attribute ||
|
||||
ScopeCtx.Kind == ScopeKind::NestedAttribute)
|
||||
JOS.attributeEnd();
|
||||
if (ScopeCtx.Kind == ScopeKind::NestedAttribute)
|
||||
JOS.objectEnd();
|
||||
ScopeHistory.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
struct DelimitedScope {
|
||||
DelimitedScope(ScopedPrinter &W) : W(W) {}
|
||||
DelimitedScope(ScopedPrinter &W) : W(&W) {}
|
||||
DelimitedScope() : W(nullptr) {}
|
||||
virtual ~DelimitedScope(){};
|
||||
ScopedPrinter &W;
|
||||
virtual void setPrinter(ScopedPrinter &W) = 0;
|
||||
ScopedPrinter *W;
|
||||
};
|
||||
|
||||
struct DictScope : DelimitedScope {
|
||||
explicit DictScope() : DelimitedScope() {}
|
||||
explicit DictScope(ScopedPrinter &W) : DelimitedScope(W) { W.objectBegin(); }
|
||||
|
||||
DictScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) {
|
||||
W.objectBegin(N);
|
||||
}
|
||||
|
||||
~DictScope() { W.objectEnd(); }
|
||||
void setPrinter(ScopedPrinter &W) override {
|
||||
this->W = &W;
|
||||
W.objectBegin();
|
||||
}
|
||||
|
||||
~DictScope() {
|
||||
if (W)
|
||||
W->objectEnd();
|
||||
}
|
||||
};
|
||||
|
||||
struct ListScope : DelimitedScope {
|
||||
explicit ListScope() : DelimitedScope() {}
|
||||
explicit ListScope(ScopedPrinter &W) : DelimitedScope(W) { W.arrayBegin(); }
|
||||
|
||||
ListScope(ScopedPrinter &W, StringRef N) : DelimitedScope(W) {
|
||||
W.arrayBegin(N);
|
||||
}
|
||||
|
||||
~ListScope() { W.arrayEnd(); }
|
||||
void setPrinter(ScopedPrinter &W) override {
|
||||
this->W = &W;
|
||||
W.arrayBegin();
|
||||
}
|
||||
|
||||
~ListScope() {
|
||||
if (W)
|
||||
W->arrayEnd();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
|
|
@ -43,4 +43,14 @@ void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str,
|
|||
}
|
||||
}
|
||||
|
||||
JSONScopedPrinter::JSONScopedPrinter(
|
||||
raw_ostream &OS, bool PrettyPrint,
|
||||
std::unique_ptr<DelimitedScope> &&OuterScope)
|
||||
: ScopedPrinter(OS, ScopedPrinter::ScopedPrinterKind::JSON),
|
||||
JOS(OS, /*Indent=*/PrettyPrint ? 2 : 0),
|
||||
OuterScope(std::move(OuterScope)) {
|
||||
if (this->OuterScope)
|
||||
this->OuterScope->setPrinter(*this);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
|
|
@ -512,7 +512,7 @@ template <typename ET>
|
|||
void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry,
|
||||
size_t Length, off_t Offset) const {
|
||||
ListScope OCC(SW, "Opcodes");
|
||||
OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length);
|
||||
OpcodeDecoder(SW).Decode(Entry, Offset, Length);
|
||||
}
|
||||
|
||||
template <typename ET>
|
||||
|
|
|
@ -13,13 +13,63 @@
|
|||
|
||||
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;
|
||||
|
||||
ScopedPrinterTest() : OS(StreamBuffer), Writer(OS) {}
|
||||
bool HasPrintedToJSON;
|
||||
|
||||
ScopedPrinterTest()
|
||||
: OS(StreamBuffer), Writer(OS), JSONWriter(OS, /*PrettyPrint=*/true),
|
||||
HasPrintedToJSON(false) {}
|
||||
|
||||
using PrintFunc = function_ref<void(ScopedPrinter &)>;
|
||||
|
||||
|
@ -27,9 +77,45 @@ protected:
|
|||
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("|");
|
||||
|
@ -147,7 +233,15 @@ TEST_F(ScopedPrinterTest, PrintEnum) {
|
|||
const char *ExpectedOut = R"(Exists: Name2 (0x2)
|
||||
DoesNotExist: 0x5
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"Exists": {
|
||||
"Value": "Name2",
|
||||
"RawValue": 2
|
||||
},
|
||||
"DoesNotExist": 5
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintFlag) {
|
||||
|
@ -251,7 +345,169 @@ FirstSecondThirdByteMask [ (0x333)
|
|||
ThirdByte3 (0x300)
|
||||
]
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"ZeroFlag": {
|
||||
"RawFlags": 0,
|
||||
"Flags": []
|
||||
},
|
||||
"NoFlag": {
|
||||
"RawFlags": 8,
|
||||
"Flags": []
|
||||
},
|
||||
"Flag1": {
|
||||
"RawFlags": 1,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "Name1",
|
||||
"Value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"Flag1&3": {
|
||||
"RawFlags": 5,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "Name1",
|
||||
"Value": 1
|
||||
},
|
||||
{
|
||||
"Name": "Name3",
|
||||
"Value": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
"ZeroFlagRaw": {
|
||||
"RawFlags": 0,
|
||||
"Flags": []
|
||||
},
|
||||
"NoFlagRaw": {
|
||||
"RawFlags": 8,
|
||||
"Flags": [
|
||||
8
|
||||
]
|
||||
},
|
||||
"Flag1Raw": {
|
||||
"RawFlags": 1,
|
||||
"Flags": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"Flag1&3Raw": {
|
||||
"RawFlags": 5,
|
||||
"Flags": [
|
||||
1,
|
||||
4
|
||||
]
|
||||
},
|
||||
"FlagSorted": {
|
||||
"RawFlags": 7,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "A",
|
||||
"Value": 4
|
||||
},
|
||||
{
|
||||
"Name": "B",
|
||||
"Value": 2
|
||||
},
|
||||
{
|
||||
"Name": "C",
|
||||
"Value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"NoBitMask": {
|
||||
"RawFlags": 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": {
|
||||
"RawFlags": 3,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "FirstByte3",
|
||||
"Value": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"SecondByteMask": {
|
||||
"RawFlags": 48,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "SecondByte3",
|
||||
"Value": 48
|
||||
}
|
||||
]
|
||||
},
|
||||
"ValueOutsideMask": {
|
||||
"RawFlags": 1,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "FirstByte1",
|
||||
"Value": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"FirstSecondByteMask": {
|
||||
"RawFlags": 255,
|
||||
"Flags": []
|
||||
},
|
||||
"FirstSecondThirdByteMask": {
|
||||
"RawFlags": 819,
|
||||
"Flags": [
|
||||
{
|
||||
"Name": "FirstByte3",
|
||||
"Value": 3
|
||||
},
|
||||
{
|
||||
"Name": "SecondByte3",
|
||||
"Value": 48
|
||||
},
|
||||
{
|
||||
"Name": "ThirdByte3",
|
||||
"Value": 768
|
||||
}
|
||||
]
|
||||
}
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintNumber) {
|
||||
|
@ -321,7 +577,31 @@ int8_t-min: -128
|
|||
apsint: 9999999999999999999999
|
||||
label: value (0)
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
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": {
|
||||
"Value": "value",
|
||||
"RawValue": 0
|
||||
}
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintBoolean) {
|
||||
|
@ -333,7 +613,12 @@ TEST_F(ScopedPrinterTest, PrintBoolean) {
|
|||
const char *ExpectedOut = R"(True: Yes
|
||||
False: No
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"True": true,
|
||||
"False": false
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintVersion) {
|
||||
|
@ -402,7 +687,56 @@ int16List: [32767, -32768]
|
|||
int8List: [127, -128]
|
||||
APSIntList: [9999999999999999999999, -9999999999999999999999]
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
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) {
|
||||
|
@ -426,7 +760,15 @@ TEST_F(ScopedPrinterTest, PrintHex) {
|
|||
const char *ExpectedOut = R"(HexNumber: 0x10
|
||||
HexLabel: Name (0x10)
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"HexNumber": 16,
|
||||
"HexLabel": {
|
||||
"Value": "Name",
|
||||
"RawValue": 16
|
||||
}
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintHexList) {
|
||||
|
@ -436,7 +778,15 @@ TEST_F(ScopedPrinterTest, PrintHexList) {
|
|||
};
|
||||
const char *ExpectedOut = R"(HexList: [0x1, 0x10, 0x100]
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"HexList": [
|
||||
1,
|
||||
16,
|
||||
256
|
||||
]
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
|
||||
|
@ -447,7 +797,18 @@ TEST_F(ScopedPrinterTest, PrintSymbolOffset) {
|
|||
const char *ExpectedOut = R"(SymbolOffset: SymbolName+0x10
|
||||
NoSymbolOffset: SymbolName+0x0
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"SymbolOffset": {
|
||||
"SymName": "SymbolName",
|
||||
"Offset": 16
|
||||
},
|
||||
"NoSymbolOffset": {
|
||||
"SymName": "SymbolName",
|
||||
"Offset": 0
|
||||
}
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintString) {
|
||||
|
@ -469,7 +830,16 @@ StringList [
|
|||
Value
|
||||
]
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"StringRef": "Value",
|
||||
"String": "Value",
|
||||
"CharArray": "Value",
|
||||
"StringList": [
|
||||
"Value"
|
||||
]
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, PrintBinary) {
|
||||
|
@ -516,7 +886,157 @@ Binary11 (
|
|||
0000: FFFF |..|
|
||||
)
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
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) {
|
||||
|
@ -524,7 +1044,11 @@ TEST_F(ScopedPrinterTest, PrintObject) {
|
|||
|
||||
const char *ExpectedOut = R"(Object: Value
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"Object": "Value"
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
||||
TEST_F(ScopedPrinterTest, StartLine) {
|
||||
|
@ -574,5 +1098,20 @@ List [
|
|||
]
|
||||
]
|
||||
)";
|
||||
verifyScopedPrinter(ExpectedOut, PrintFunc);
|
||||
|
||||
const char *JSONExpectedOut = R"({
|
||||
"Object": {
|
||||
"ObjectInObject": {},
|
||||
"ListInObject": []
|
||||
},
|
||||
"List": [
|
||||
{
|
||||
"ObjectInList": {}
|
||||
},
|
||||
{
|
||||
"ListInList": []
|
||||
}
|
||||
]
|
||||
})";
|
||||
verifyAll(ExpectedOut, JSONExpectedOut, PrintFunc);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue