Fix two bugs in DocNode's comparison operators and add a new Document::copyNode() method: 1. operator== was implemented via operator<, which hits llvm_unreachable for Array/Map nodes. Implement operator== directly with recursive value comparison for all node types. 2. operator< compared KindAndDoc pointers, causing cross-document nodes of the same type and value to silently produce wrong results. Compare by kind then by value instead. 3. Add Document::copyNode() for deep copying nodes between Documents with independent memory ownership.
765 lines
23 KiB
C++
765 lines
23 KiB
C++
//===- MsgPackDocumentTest.cpp --------------------------------------------===//
|
|
//
|
|
// 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/BinaryFormat/MsgPackDocument.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
using namespace msgpack;
|
|
|
|
TEST(MsgPackDocument, DocNodeTest) {
|
|
Document Doc;
|
|
|
|
DocNode Int1 = Doc.getNode(1), Int2 = Doc.getNode(2);
|
|
DocNode Str1 = Doc.getNode("ab"), Str2 = Doc.getNode("ab");
|
|
|
|
ASSERT_TRUE(Int1 != Int2);
|
|
ASSERT_TRUE(Str1 == Str2);
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeEmptyAndNilEquality) {
|
|
Document Doc1, Doc2;
|
|
|
|
// Two empty nodes are equal.
|
|
EXPECT_FALSE(Doc1.getEmptyNode() != Doc1.getEmptyNode());
|
|
// Cross-document empty nodes are equal.
|
|
EXPECT_FALSE(Doc1.getEmptyNode() != Doc2.getEmptyNode());
|
|
// Default-constructed (no document) empty nodes are equal.
|
|
DocNode Default1, Default2;
|
|
EXPECT_FALSE(Default1 != Default2);
|
|
// Empty vs non-empty are not equal.
|
|
EXPECT_FALSE(Doc1.getEmptyNode() == Doc1.getNode(0));
|
|
|
|
// Two nil nodes are equal.
|
|
EXPECT_FALSE(Doc1.getNode() != Doc1.getNode());
|
|
// Cross-document nil nodes are equal.
|
|
EXPECT_FALSE(Doc1.getNode() != Doc2.getNode());
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeDifferentTypesNotEqual) {
|
|
Document Doc;
|
|
// Int vs String.
|
|
EXPECT_FALSE(Doc.getNode(1) == Doc.getNode("1"));
|
|
// Int vs UInt.
|
|
EXPECT_FALSE(Doc.getNode(int64_t(1)) == Doc.getNode(uint64_t(1)));
|
|
// Boolean vs Int.
|
|
EXPECT_FALSE(Doc.getNode(true) == Doc.getNode(1));
|
|
// Scalar vs Array.
|
|
DocNode Arr = Doc.getArrayNode();
|
|
EXPECT_FALSE(Doc.getNode(1) == Arr);
|
|
// Scalar vs Map.
|
|
DocNode Map = Doc.getMapNode();
|
|
EXPECT_FALSE(Doc.getNode(1) == Map);
|
|
// Array vs Map.
|
|
EXPECT_FALSE(Arr == Map);
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeCrossDocumentScalarEquality) {
|
|
Document Doc1, Doc2;
|
|
// Same values across documents should be equal.
|
|
EXPECT_FALSE(Doc1.getNode(42) != Doc2.getNode(42));
|
|
EXPECT_FALSE(Doc1.getNode(42U) != Doc2.getNode(42U));
|
|
EXPECT_FALSE(Doc1.getNode(int64_t(-1)) != Doc2.getNode(int64_t(-1)));
|
|
EXPECT_FALSE(Doc1.getNode(true) != Doc2.getNode(true));
|
|
EXPECT_FALSE(Doc1.getNode(3.14) != Doc2.getNode(3.14));
|
|
EXPECT_FALSE(Doc1.getNode("hello") != Doc2.getNode("hello"));
|
|
|
|
// Different values across documents should not be equal.
|
|
EXPECT_FALSE(Doc1.getNode(1) == Doc2.getNode(2));
|
|
EXPECT_FALSE(Doc1.getNode("foo") == Doc2.getNode("bar"));
|
|
EXPECT_FALSE(Doc1.getNode(true) == Doc2.getNode(false));
|
|
EXPECT_FALSE(Doc1.getNode(1U) == Doc2.getNode(2U));
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeCrossDocumentScalarOrdering) {
|
|
Document Doc1, Doc2;
|
|
// operator< should compare by value across documents.
|
|
EXPECT_TRUE(Doc1.getNode(1) < Doc2.getNode(2));
|
|
EXPECT_FALSE(Doc1.getNode(2) < Doc2.getNode(1));
|
|
EXPECT_FALSE(Doc1.getNode(1) < Doc2.getNode(1));
|
|
|
|
EXPECT_TRUE(Doc1.getNode("abc") < Doc2.getNode("def"));
|
|
EXPECT_FALSE(Doc1.getNode("def") < Doc2.getNode("abc"));
|
|
|
|
EXPECT_TRUE(Doc1.getNode(1U) < Doc2.getNode(2U));
|
|
EXPECT_FALSE(Doc1.getNode(2U) < Doc2.getNode(1U));
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeArrayEquality) {
|
|
Document Doc;
|
|
auto A1 = Doc.getArrayNode();
|
|
A1.push_back(Doc.getNode(int64_t(1)));
|
|
A1.push_back(Doc.getNode(int64_t(2)));
|
|
|
|
auto A2 = Doc.getArrayNode();
|
|
A2.push_back(Doc.getNode(int64_t(1)));
|
|
A2.push_back(Doc.getNode(int64_t(2)));
|
|
|
|
// Same contents should be equal.
|
|
DocNode N1 = A1, N2 = A2;
|
|
EXPECT_FALSE(N1 != N2);
|
|
|
|
// Different contents should not be equal.
|
|
auto A3 = Doc.getArrayNode();
|
|
A3.push_back(Doc.getNode(int64_t(1)));
|
|
A3.push_back(Doc.getNode(int64_t(99)));
|
|
DocNode N3 = A3;
|
|
EXPECT_FALSE(N1 == N3);
|
|
|
|
// Different sizes should not be equal.
|
|
auto A4 = Doc.getArrayNode();
|
|
A4.push_back(Doc.getNode(int64_t(1)));
|
|
DocNode N4 = A4;
|
|
EXPECT_FALSE(N1 == N4);
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeMapEquality) {
|
|
Document Doc;
|
|
auto M1 = Doc.getMapNode();
|
|
M1["x"] = 10;
|
|
M1["y"] = 20;
|
|
|
|
auto M2 = Doc.getMapNode();
|
|
M2["x"] = 10;
|
|
M2["y"] = 20;
|
|
|
|
DocNode N1 = M1, N2 = M2;
|
|
EXPECT_FALSE(N1 != N2);
|
|
|
|
// Different value.
|
|
auto M3 = Doc.getMapNode();
|
|
M3["x"] = 10;
|
|
M3["y"] = 99;
|
|
DocNode N3 = M3;
|
|
EXPECT_FALSE(N1 == N3);
|
|
|
|
// Different key.
|
|
auto M4 = Doc.getMapNode();
|
|
M4["x"] = 10;
|
|
M4["z"] = 20;
|
|
DocNode N4 = M4;
|
|
EXPECT_FALSE(N1 == N4);
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeCrossDocumentArrayEquality) {
|
|
Document Doc1, Doc2;
|
|
auto A1 = Doc1.getArrayNode();
|
|
A1.push_back(Doc1.getNode("hello"));
|
|
A1.push_back(Doc1.getNode(42));
|
|
|
|
auto A2 = Doc2.getArrayNode();
|
|
A2.push_back(Doc2.getNode("hello"));
|
|
A2.push_back(Doc2.getNode(42));
|
|
|
|
DocNode N1 = A1, N2 = A2;
|
|
EXPECT_FALSE(N1 != N2);
|
|
|
|
auto A3 = Doc2.getArrayNode();
|
|
A3.push_back(Doc2.getNode("hello"));
|
|
A3.push_back(Doc2.getNode(99));
|
|
DocNode N3 = A3;
|
|
EXPECT_FALSE(N1 == N3);
|
|
}
|
|
|
|
TEST(MsgPackDocument, DocNodeCrossDocumentMapEquality) {
|
|
Document Doc1, Doc2;
|
|
auto M1 = Doc1.getMapNode();
|
|
M1["key"] = Doc1.getNode("value");
|
|
|
|
auto M2 = Doc2.getMapNode();
|
|
M2["key"] = Doc2.getNode("value");
|
|
|
|
DocNode N1 = M1, N2 = M2;
|
|
EXPECT_FALSE(N1 != N2);
|
|
|
|
auto M3 = Doc2.getMapNode();
|
|
M3["key"] = Doc2.getNode("other");
|
|
DocNode N3 = M3;
|
|
EXPECT_FALSE(N1 == N3);
|
|
}
|
|
|
|
TEST(MsgPackDocument, CopyNodeEmpty) {
|
|
Document Src, Dst;
|
|
auto Copied = Dst.copyNode(Src.getEmptyNode());
|
|
EXPECT_TRUE(Copied.isEmpty());
|
|
}
|
|
|
|
TEST(MsgPackDocument, CopyNodeScalar) {
|
|
Document Src, Dst;
|
|
auto Node = Src.getNode("hello", /*Copy=*/true);
|
|
auto Copied = Dst.copyNode(Node);
|
|
EXPECT_FALSE(Node != Copied);
|
|
EXPECT_EQ(Copied.getKind(), Type::String);
|
|
EXPECT_EQ(Copied.getString(), "hello");
|
|
}
|
|
|
|
TEST(MsgPackDocument, CopyNodeArray) {
|
|
Document Src, Dst;
|
|
auto A = Src.getArrayNode();
|
|
A.push_back(Src.getNode(int64_t(1)));
|
|
A.push_back(Src.getNode("two", /*Copy=*/true));
|
|
A.push_back(Src.getNode(3.0));
|
|
|
|
DocNode SrcNode = A;
|
|
auto Copied = Dst.copyNode(SrcNode);
|
|
EXPECT_FALSE(SrcNode != Copied);
|
|
EXPECT_EQ(Copied.getArray().size(), 3u);
|
|
EXPECT_EQ(Copied.getArray()[0].getInt(), int64_t(1));
|
|
EXPECT_EQ(Copied.getArray()[1].getString(), "two");
|
|
EXPECT_EQ(Copied.getArray()[2].getFloat(), 3.0);
|
|
}
|
|
|
|
TEST(MsgPackDocument, CopyNodeMap) {
|
|
Document Src, Dst;
|
|
auto M = Src.getMapNode();
|
|
M["name"] = Src.getNode("test", /*Copy=*/true);
|
|
M["count"] = 42;
|
|
|
|
DocNode SrcNode = M;
|
|
auto Copied = Dst.copyNode(SrcNode);
|
|
EXPECT_FALSE(SrcNode != Copied);
|
|
|
|
// Verify by iterating the map directly.
|
|
auto &CopiedMap = Copied.getMap();
|
|
EXPECT_EQ(CopiedMap.size(), 2u);
|
|
for (auto &Entry : CopiedMap) {
|
|
EXPECT_TRUE(Entry.first.isString());
|
|
if (Entry.first.getString() == "name")
|
|
EXPECT_EQ(Entry.second.getString(), "test");
|
|
else if (Entry.first.getString() == "count")
|
|
EXPECT_EQ(Entry.second.getInt(), int64_t(42));
|
|
else
|
|
FAIL() << "unexpected key: " << Entry.first.toString();
|
|
}
|
|
}
|
|
|
|
TEST(MsgPackDocument, CopyNodeNested) {
|
|
Document Src, Dst;
|
|
auto M = Src.getMapNode();
|
|
auto Inner = Src.getArrayNode();
|
|
Inner.push_back(Src.getNode(int64_t(1)));
|
|
Inner.push_back(Src.getNode(int64_t(2)));
|
|
M["arr"] = Inner;
|
|
M["val"] = Src.getNode("x", /*Copy=*/true);
|
|
|
|
DocNode SrcNode = M;
|
|
auto Copied = Dst.copyNode(SrcNode);
|
|
EXPECT_FALSE(SrcNode != Copied);
|
|
auto &CopiedMap = Copied.getMap();
|
|
EXPECT_TRUE(CopiedMap["arr"].isArray());
|
|
EXPECT_EQ(CopiedMap["arr"].getArray().size(), 2u);
|
|
EXPECT_EQ(CopiedMap["arr"].getArray()[0].getInt(), int64_t(1));
|
|
}
|
|
|
|
TEST(MsgPackDocument, CopyNodeIndependence) {
|
|
Document Src, Dst;
|
|
auto A = Src.getArrayNode();
|
|
A.push_back(Src.getNode(int64_t(1)));
|
|
A.push_back(Src.getNode(int64_t(2)));
|
|
|
|
DocNode SrcNode = A;
|
|
auto Copied = Dst.copyNode(SrcNode);
|
|
EXPECT_FALSE(SrcNode != Copied);
|
|
|
|
// Mutate the source — the copy should be unaffected.
|
|
A.push_back(Src.getNode(int64_t(3)));
|
|
EXPECT_EQ(A.size(), 3u);
|
|
EXPECT_EQ(Copied.getArray().size(), 2u);
|
|
|
|
// Mutate the copy — the source should be unaffected.
|
|
Copied.getArray().push_back(Dst.getNode(int64_t(10)));
|
|
Copied.getArray().push_back(Dst.getNode(int64_t(20)));
|
|
EXPECT_EQ(Copied.getArray().size(), 4u);
|
|
EXPECT_EQ(A.size(), 3u);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadBoolean) {
|
|
Document Doc1;
|
|
bool Ok = Doc1.readFromBlob(StringRef("\xC2", 1), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc1.getRoot().getKind(), Type::Boolean);
|
|
ASSERT_EQ(Doc1.getRoot().getBool(), false);
|
|
Document Doc2;
|
|
Ok = Doc2.readFromBlob(StringRef("\xC3", 1), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc2.getRoot().getKind(), Type::Boolean);
|
|
ASSERT_EQ(Doc2.getRoot().getBool(), true);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadInt) {
|
|
Document Doc1;
|
|
bool Ok = Doc1.readFromBlob(StringRef("\xD0\x00", 2), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc1.getRoot().getKind(), Type::Int);
|
|
ASSERT_EQ(Doc1.getRoot().getInt(), 0);
|
|
Document Doc2;
|
|
Ok = Doc2.readFromBlob(StringRef("\xFF", 1), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc2.getRoot().getKind(), Type::Int);
|
|
ASSERT_EQ(Doc2.getRoot().getInt(), -1);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadUInt) {
|
|
Document Doc1;
|
|
bool Ok = Doc1.readFromBlob(StringRef("\xCC\x00", 2), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc1.getRoot().getKind(), Type::UInt);
|
|
ASSERT_EQ(Doc1.getRoot().getUInt(), 0U);
|
|
Document Doc2;
|
|
Ok = Doc2.readFromBlob(StringRef("\x01", 1), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc2.getRoot().getKind(), Type::UInt);
|
|
ASSERT_EQ(Doc2.getRoot().getUInt(), 1U);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadFloat) {
|
|
Document Doc1;
|
|
bool Ok =
|
|
Doc1.readFromBlob(StringRef("\xCA\x3F\x80\x00\x00", 5), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc1.getRoot().getKind(), Type::Float);
|
|
ASSERT_EQ(Doc1.getRoot().getFloat(), 1.0);
|
|
Document Doc2;
|
|
Ok = Doc2.readFromBlob(StringRef("\xCB\x48\x3D\x63\x29\xF1\xC3\x5C\xA5", 9),
|
|
/*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc2.getRoot().getKind(), Type::Float);
|
|
ASSERT_EQ(Doc2.getRoot().getFloat(), 1e40);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadBinary) {
|
|
Document Doc;
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
bool Ok =
|
|
Doc.readFromBlob(StringRef("\xC4\x4\x1\x2\x3\x4", 6), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc.getRoot().getKind(), Type::Binary);
|
|
ASSERT_EQ(Doc.getRoot().getBinary().getBuffer(),
|
|
StringRef(reinterpret_cast<const char *>(data), 4));
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadMergeArray) {
|
|
Document Doc;
|
|
bool Ok = Doc.readFromBlob(StringRef("\x92\xd0\x01\xc0"), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc.getRoot().getKind(), Type::Array);
|
|
auto A = Doc.getRoot().getArray();
|
|
ASSERT_EQ(A.size(), 2u);
|
|
auto SI = A[0];
|
|
ASSERT_EQ(SI.getKind(), Type::Int);
|
|
ASSERT_EQ(SI.getInt(), 1);
|
|
auto SN = A[1];
|
|
ASSERT_EQ(SN.getKind(), Type::Nil);
|
|
|
|
Ok = Doc.readFromBlob(StringRef("\x91\xd0\x2a"), /*Multi=*/false,
|
|
[](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
|
|
// Allow array, merging into existing elements, ORing
|
|
// ints.
|
|
if (DestNode->getKind() == Type::Int &&
|
|
SrcNode.getKind() == Type::Int) {
|
|
*DestNode = DestNode->getDocument()->getNode(
|
|
DestNode->getInt() | SrcNode.getInt());
|
|
return 0;
|
|
}
|
|
return DestNode->isArray() && SrcNode.isArray() ? 0
|
|
: -1;
|
|
});
|
|
ASSERT_TRUE(Ok);
|
|
A = Doc.getRoot().getArray();
|
|
ASSERT_EQ(A.size(), 2u);
|
|
SI = A[0];
|
|
ASSERT_EQ(SI.getKind(), Type::Int);
|
|
ASSERT_EQ(SI.getInt(), 43);
|
|
SN = A[1];
|
|
ASSERT_EQ(SN.getKind(), Type::Nil);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadAppendArray) {
|
|
Document Doc;
|
|
bool Ok = Doc.readFromBlob(StringRef("\x92\xd0\x01\xc0"), /*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc.getRoot().getKind(), Type::Array);
|
|
auto A = Doc.getRoot().getArray();
|
|
ASSERT_EQ(A.size(), 2u);
|
|
auto SI = A[0];
|
|
ASSERT_EQ(SI.getKind(), Type::Int);
|
|
ASSERT_EQ(SI.getInt(), 1);
|
|
auto SN = A[1];
|
|
ASSERT_EQ(SN.getKind(), Type::Nil);
|
|
|
|
Ok = Doc.readFromBlob(StringRef("\x91\xd0\x2a"), /*Multi=*/false,
|
|
[](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
|
|
// Allow array, appending after existing elements
|
|
return DestNode->isArray() && SrcNode.isArray()
|
|
? DestNode->getArray().size()
|
|
: -1;
|
|
});
|
|
ASSERT_TRUE(Ok);
|
|
A = Doc.getRoot().getArray();
|
|
ASSERT_EQ(A.size(), 3u);
|
|
SI = A[0];
|
|
ASSERT_EQ(SI.getKind(), Type::Int);
|
|
ASSERT_EQ(SI.getInt(), 1);
|
|
SN = A[1];
|
|
ASSERT_EQ(SN.getKind(), Type::Nil);
|
|
SI = A[2];
|
|
ASSERT_EQ(SI.getKind(), Type::Int);
|
|
ASSERT_EQ(SI.getInt(), 42);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestReadMergeMap) {
|
|
Document Doc;
|
|
bool Ok = Doc.readFromBlob(StringRef("\x82\xa3"
|
|
"foo"
|
|
"\xd0\x01\xa3"
|
|
"bar"
|
|
"\xd0\x02"),
|
|
/*Multi=*/false);
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc.getRoot().getKind(), Type::Map);
|
|
auto M = Doc.getRoot().getMap();
|
|
ASSERT_EQ(M.size(), 2u);
|
|
auto FooS = M["foo"];
|
|
ASSERT_EQ(FooS.getKind(), Type::Int);
|
|
ASSERT_EQ(FooS.getInt(), 1);
|
|
auto BarS = M["bar"];
|
|
ASSERT_EQ(BarS.getKind(), Type::Int);
|
|
ASSERT_EQ(BarS.getInt(), 2);
|
|
|
|
Ok = Doc.readFromBlob(StringRef("\x82\xa3"
|
|
"foz"
|
|
"\xd0\x03\xa3"
|
|
"baz"
|
|
"\xd0\x04"),
|
|
/*Multi=*/false,
|
|
[](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
|
|
return DestNode->isMap() && SrcNode.isMap() ? 0 : -1;
|
|
});
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(M.size(), 4u);
|
|
FooS = M["foo"];
|
|
ASSERT_EQ(FooS.getKind(), Type::Int);
|
|
ASSERT_EQ(FooS.getInt(), 1);
|
|
BarS = M["bar"];
|
|
ASSERT_EQ(BarS.getKind(), Type::Int);
|
|
ASSERT_EQ(BarS.getInt(), 2);
|
|
auto FozS = M["foz"];
|
|
ASSERT_EQ(FozS.getKind(), Type::Int);
|
|
ASSERT_EQ(FozS.getInt(), 3);
|
|
auto BazS = M["baz"];
|
|
ASSERT_EQ(BazS.getKind(), Type::Int);
|
|
ASSERT_EQ(BazS.getInt(), 4);
|
|
|
|
Ok = Doc.readFromBlob(
|
|
StringRef("\x82\xa3"
|
|
"foz"
|
|
"\xd0\x06\xa3"
|
|
"bay"
|
|
"\xd0\x08"),
|
|
/*Multi=*/false, [](DocNode *Dest, DocNode Src, DocNode MapKey) {
|
|
// Merger function that merges two ints by ORing their values, as long
|
|
// as the map key is "foz".
|
|
if (Src.isMap())
|
|
return Dest->isMap();
|
|
if (Src.isArray())
|
|
return Dest->isArray();
|
|
if (MapKey.isString() && MapKey.getString() == "foz" &&
|
|
Dest->getKind() == Type::Int && Src.getKind() == Type::Int) {
|
|
*Dest = Src.getDocument()->getNode(Dest->getInt() | Src.getInt());
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(M.size(), 5u);
|
|
FooS = M["foo"];
|
|
ASSERT_EQ(FooS.getKind(), Type::Int);
|
|
ASSERT_EQ(FooS.getInt(), 1);
|
|
BarS = M["bar"];
|
|
ASSERT_EQ(BarS.getKind(), Type::Int);
|
|
ASSERT_EQ(BarS.getInt(), 2);
|
|
FozS = M["foz"];
|
|
ASSERT_EQ(FozS.getKind(), Type::Int);
|
|
ASSERT_EQ(FozS.getInt(), 7);
|
|
BazS = M["baz"];
|
|
ASSERT_EQ(BazS.getKind(), Type::Int);
|
|
ASSERT_EQ(BazS.getInt(), 4);
|
|
auto BayS = M["bay"];
|
|
ASSERT_EQ(BayS.getKind(), Type::Int);
|
|
ASSERT_EQ(BayS.getInt(), 8);
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteBoolean) {
|
|
Document Doc;
|
|
Doc.getRoot() = true;
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\xc3");
|
|
Doc.getRoot() = false;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\xc2");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteInt) {
|
|
Document Doc;
|
|
Doc.getRoot() = 1;
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\x01");
|
|
Doc.getRoot() = -1;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\xFF");
|
|
Doc.getRoot() = -4096;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, StringRef("\xD1\xF0\x00", 3));
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteUInt) {
|
|
Document Doc;
|
|
Doc.getRoot() = 1U;
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\x01");
|
|
Doc.getRoot() = 4096U;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, StringRef("\xCD\x10\x00", 3));
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteFloat) {
|
|
Document Doc;
|
|
Doc.getRoot() = 1.0;
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, StringRef("\xCA\x3F\x80\x00\x00", 5));
|
|
Doc.getRoot() = 1.0f;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, StringRef("\xCA\x3F\x80\x00\x00", 5));
|
|
Doc.getRoot() = 1e40;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\xCB\x48\x3D\x63\x29\xF1\xC3\x5C\xA5");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteBinary) {
|
|
uint8_t data[] = {1, 2, 3, 4};
|
|
Document Doc;
|
|
Doc.getRoot() = MemoryBufferRef(
|
|
StringRef(reinterpret_cast<const char *>(data), sizeof(data)), "");
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\xC4\x4\x1\x2\x3\x4");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteArray) {
|
|
Document Doc;
|
|
auto A = Doc.getRoot().getArray(/*Convert=*/true);
|
|
A.push_back(Doc.getNode(int64_t(1)));
|
|
A.push_back(Doc.getNode());
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\x92\x01\xc0");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestWriteMap) {
|
|
Document Doc;
|
|
auto M = Doc.getRoot().getMap(/*Convert=*/true);
|
|
M["foo"] = 1;
|
|
M["bar"] = 2;
|
|
std::string Buffer;
|
|
Doc.writeToBlob(Buffer);
|
|
ASSERT_EQ(Buffer, "\x82\xa3"
|
|
"bar"
|
|
"\x02\xa3"
|
|
"foo"
|
|
"\x01");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestOutputYAMLArray) {
|
|
Document Doc;
|
|
auto A = Doc.getRoot().getArray(/*Convert=*/true);
|
|
A.push_back(Doc.getNode(int64_t(1)));
|
|
A.push_back(Doc.getNode(int64_t(2)));
|
|
std::string Buffer;
|
|
raw_string_ostream OStream(Buffer);
|
|
Doc.toYAML(OStream);
|
|
ASSERT_EQ(OStream.str(), "---\n- 1\n- 2\n...\n");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestInputYAMLArray) {
|
|
Document Doc;
|
|
bool Ok = Doc.fromYAML("---\n- !int 0x1\n- !str 2\n...\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc.getRoot().getKind(), Type::Array);
|
|
auto A = Doc.getRoot().getArray();
|
|
ASSERT_EQ(A.size(), 2u);
|
|
auto SI = A[0];
|
|
ASSERT_EQ(SI.getKind(), Type::UInt);
|
|
ASSERT_EQ(SI.getUInt(), 1u);
|
|
auto SS = A[1];
|
|
ASSERT_EQ(SS.getKind(), Type::String);
|
|
ASSERT_EQ(SS.getString(), "2");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestOutputYAMLMap) {
|
|
Document Doc;
|
|
auto M = Doc.getRoot().getMap(/*Convert=*/true);
|
|
M["foo"] = 1;
|
|
M["bar"] = 2U;
|
|
auto N = Doc.getMapNode();
|
|
M["qux"] = N;
|
|
N["baz"] = true;
|
|
std::string Buffer;
|
|
raw_string_ostream OStream(Buffer);
|
|
Doc.toYAML(OStream);
|
|
ASSERT_EQ(OStream.str(), "---\n"
|
|
"bar: 2\n"
|
|
"foo: 1\n"
|
|
"qux:\n"
|
|
" baz: true\n"
|
|
"...\n");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestOutputYAMLMapWithErase) {
|
|
Document Doc;
|
|
auto M = Doc.getRoot().getMap(/*Convert=*/true);
|
|
M["foo"] = 1;
|
|
M["bar"] = 2U;
|
|
auto N = Doc.getMapNode();
|
|
M["qux"] = N;
|
|
N["baz"] = true;
|
|
M.erase(Doc.getNode("bar"));
|
|
std::string Buffer;
|
|
raw_string_ostream OStream(Buffer);
|
|
Doc.toYAML(OStream);
|
|
ASSERT_EQ(OStream.str(), "---\n"
|
|
"foo: 1\n"
|
|
"qux:\n"
|
|
" baz: true\n"
|
|
"...\n");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestOutputYAMLMapHex) {
|
|
Document Doc;
|
|
Doc.setHexMode();
|
|
auto M = Doc.getRoot().getMap(/*Convert=*/true);
|
|
M["foo"] = 1;
|
|
M["bar"] = 2U;
|
|
auto N = Doc.getMapNode();
|
|
M["qux"] = N;
|
|
N["baz"] = true;
|
|
std::string Buffer;
|
|
raw_string_ostream OStream(Buffer);
|
|
Doc.toYAML(OStream);
|
|
ASSERT_EQ(OStream.str(), "---\n"
|
|
"bar: 0x2\n"
|
|
"foo: 1\n"
|
|
"qux:\n"
|
|
" baz: true\n"
|
|
"...\n");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestInputYAMLMap) {
|
|
Document Doc;
|
|
bool Ok = Doc.fromYAML("---\nfoo: !int 0x1\nbaz: !str 2\n...\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(Doc.getRoot().getKind(), Type::Map);
|
|
auto M = Doc.getRoot().getMap();
|
|
ASSERT_EQ(M.size(), 2u);
|
|
auto SI = M["foo"];
|
|
ASSERT_EQ(SI.getKind(), Type::UInt);
|
|
ASSERT_EQ(SI.getUInt(), 1u);
|
|
auto SS = M["baz"];
|
|
ASSERT_EQ(SS.getKind(), Type::String);
|
|
ASSERT_EQ(SS.getString(), "2");
|
|
}
|
|
|
|
TEST(MsgPackDocument, TestYAMLBoolean) {
|
|
Document Doc;
|
|
auto GetFirst = [](Document &Doc) { return Doc.getRoot().getArray()[0]; };
|
|
auto ToYAML = [](Document &Doc) {
|
|
std::string S;
|
|
raw_string_ostream OS(S);
|
|
Doc.toYAML(OS);
|
|
return S;
|
|
};
|
|
|
|
bool Ok;
|
|
|
|
Ok = Doc.fromYAML("- n\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::String);
|
|
ASSERT_EQ(GetFirst(Doc).getString(), "n");
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- n\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- y\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::String);
|
|
ASSERT_EQ(GetFirst(Doc).getString(), "y");
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- y\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- no\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::String);
|
|
ASSERT_EQ(GetFirst(Doc).getString(), "no");
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- no\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- yes\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::String);
|
|
ASSERT_EQ(GetFirst(Doc).getString(), "yes");
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- yes\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- false\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::Boolean);
|
|
ASSERT_EQ(GetFirst(Doc).getBool(), false);
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- false\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- true\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::Boolean);
|
|
ASSERT_EQ(GetFirst(Doc).getBool(), true);
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- true\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- !str false\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::String);
|
|
ASSERT_EQ(GetFirst(Doc).getString(), "false");
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- !str 'false'\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- !str true\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::String);
|
|
ASSERT_EQ(GetFirst(Doc).getString(), "true");
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- !str 'true'\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- !bool false\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::Boolean);
|
|
ASSERT_EQ(GetFirst(Doc).getBool(), false);
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- false\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- !bool true\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::Boolean);
|
|
ASSERT_EQ(GetFirst(Doc).getBool(), true);
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- true\n...\n");
|
|
|
|
// FIXME: A fix for these requires changes in YAMLParser/YAMLTraits.
|
|
Ok = Doc.fromYAML("- \"false\"\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::Boolean);
|
|
ASSERT_EQ(GetFirst(Doc).getBool(), false);
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- false\n...\n");
|
|
|
|
Ok = Doc.fromYAML("- \"true\"\n");
|
|
ASSERT_TRUE(Ok);
|
|
ASSERT_EQ(GetFirst(Doc).getKind(), Type::Boolean);
|
|
ASSERT_EQ(GetFirst(Doc).getBool(), true);
|
|
ASSERT_EQ(ToYAML(Doc), "---\n- true\n...\n");
|
|
}
|