1 //===- MsgPackDocumentTest.cpp --------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/BinaryFormat/MsgPackDocument.h"
11 #include "gtest/gtest.h"
12
13 using namespace llvm;
14 using namespace msgpack;
15
TEST(MsgPackDocument,DocNodeTest)16 TEST(MsgPackDocument, DocNodeTest) {
17 Document Doc;
18
19 DocNode Int1 = Doc.getNode(1), Int2 = Doc.getNode(2);
20 DocNode Str1 = Doc.getNode("ab"), Str2 = Doc.getNode("ab");
21
22 ASSERT_TRUE(Int1 != Int2);
23 ASSERT_TRUE(Str1 == Str2);
24 }
25
TEST(MsgPackDocument,TestReadInt)26 TEST(MsgPackDocument, TestReadInt) {
27 Document Doc;
28 bool Ok = Doc.readFromBlob(StringRef("\xd0\x00", 2), /*Multi=*/false);
29 ASSERT_TRUE(Ok);
30 ASSERT_EQ(Doc.getRoot().getKind(), Type::Int);
31 ASSERT_EQ(Doc.getRoot().getInt(), 0);
32 }
33
TEST(MsgPackDocument,TestReadMergeArray)34 TEST(MsgPackDocument, TestReadMergeArray) {
35 Document Doc;
36 bool Ok = Doc.readFromBlob(StringRef("\x92\xd0\x01\xc0"), /*Multi=*/false);
37 ASSERT_TRUE(Ok);
38 ASSERT_EQ(Doc.getRoot().getKind(), Type::Array);
39 auto A = Doc.getRoot().getArray();
40 ASSERT_EQ(A.size(), 2u);
41 auto SI = A[0];
42 ASSERT_EQ(SI.getKind(), Type::Int);
43 ASSERT_EQ(SI.getInt(), 1);
44 auto SN = A[1];
45 ASSERT_EQ(SN.getKind(), Type::Nil);
46
47 Ok = Doc.readFromBlob(StringRef("\x91\xd0\x2a"), /*Multi=*/false,
48 [](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
49 // Allow array, merging into existing elements, ORing
50 // ints.
51 if (DestNode->getKind() == Type::Int &&
52 SrcNode.getKind() == Type::Int) {
53 *DestNode = DestNode->getDocument()->getNode(
54 DestNode->getInt() | SrcNode.getInt());
55 return 0;
56 }
57 return DestNode->isArray() && SrcNode.isArray() ? 0
58 : -1;
59 });
60 ASSERT_TRUE(Ok);
61 A = Doc.getRoot().getArray();
62 ASSERT_EQ(A.size(), 2u);
63 SI = A[0];
64 ASSERT_EQ(SI.getKind(), Type::Int);
65 ASSERT_EQ(SI.getInt(), 43);
66 SN = A[1];
67 ASSERT_EQ(SN.getKind(), Type::Nil);
68 }
69
TEST(MsgPackDocument,TestReadAppendArray)70 TEST(MsgPackDocument, TestReadAppendArray) {
71 Document Doc;
72 bool Ok = Doc.readFromBlob(StringRef("\x92\xd0\x01\xc0"), /*Multi=*/false);
73 ASSERT_TRUE(Ok);
74 ASSERT_EQ(Doc.getRoot().getKind(), Type::Array);
75 auto A = Doc.getRoot().getArray();
76 ASSERT_EQ(A.size(), 2u);
77 auto SI = A[0];
78 ASSERT_EQ(SI.getKind(), Type::Int);
79 ASSERT_EQ(SI.getInt(), 1);
80 auto SN = A[1];
81 ASSERT_EQ(SN.getKind(), Type::Nil);
82
83 Ok = Doc.readFromBlob(StringRef("\x91\xd0\x2a"), /*Multi=*/false,
84 [](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
85 // Allow array, appending after existing elements
86 return DestNode->isArray() && SrcNode.isArray()
87 ? DestNode->getArray().size()
88 : -1;
89 });
90 ASSERT_TRUE(Ok);
91 A = Doc.getRoot().getArray();
92 ASSERT_EQ(A.size(), 3u);
93 SI = A[0];
94 ASSERT_EQ(SI.getKind(), Type::Int);
95 ASSERT_EQ(SI.getInt(), 1);
96 SN = A[1];
97 ASSERT_EQ(SN.getKind(), Type::Nil);
98 SI = A[2];
99 ASSERT_EQ(SI.getKind(), Type::Int);
100 ASSERT_EQ(SI.getInt(), 42);
101 }
102
TEST(MsgPackDocument,TestReadMergeMap)103 TEST(MsgPackDocument, TestReadMergeMap) {
104 Document Doc;
105 bool Ok = Doc.readFromBlob(StringRef("\x82\xa3"
106 "foo"
107 "\xd0\x01\xa3"
108 "bar"
109 "\xd0\x02"),
110 /*Multi=*/false);
111 ASSERT_TRUE(Ok);
112 ASSERT_EQ(Doc.getRoot().getKind(), Type::Map);
113 auto M = Doc.getRoot().getMap();
114 ASSERT_EQ(M.size(), 2u);
115 auto FooS = M["foo"];
116 ASSERT_EQ(FooS.getKind(), Type::Int);
117 ASSERT_EQ(FooS.getInt(), 1);
118 auto BarS = M["bar"];
119 ASSERT_EQ(BarS.getKind(), Type::Int);
120 ASSERT_EQ(BarS.getInt(), 2);
121
122 Ok = Doc.readFromBlob(StringRef("\x82\xa3"
123 "foz"
124 "\xd0\x03\xa3"
125 "baz"
126 "\xd0\x04"),
127 /*Multi=*/false,
128 [](DocNode *DestNode, DocNode SrcNode, DocNode MapKey) {
129 return DestNode->isMap() && SrcNode.isMap() ? 0 : -1;
130 });
131 ASSERT_TRUE(Ok);
132 ASSERT_EQ(M.size(), 4u);
133 FooS = M["foo"];
134 ASSERT_EQ(FooS.getKind(), Type::Int);
135 ASSERT_EQ(FooS.getInt(), 1);
136 BarS = M["bar"];
137 ASSERT_EQ(BarS.getKind(), Type::Int);
138 ASSERT_EQ(BarS.getInt(), 2);
139 auto FozS = M["foz"];
140 ASSERT_EQ(FozS.getKind(), Type::Int);
141 ASSERT_EQ(FozS.getInt(), 3);
142 auto BazS = M["baz"];
143 ASSERT_EQ(BazS.getKind(), Type::Int);
144 ASSERT_EQ(BazS.getInt(), 4);
145
146 Ok = Doc.readFromBlob(
147 StringRef("\x82\xa3"
148 "foz"
149 "\xd0\x06\xa3"
150 "bay"
151 "\xd0\x08"),
152 /*Multi=*/false, [](DocNode *Dest, DocNode Src, DocNode MapKey) {
153 // Merger function that merges two ints by ORing their values, as long
154 // as the map key is "foz".
155 if (Src.isMap())
156 return Dest->isMap();
157 if (Src.isArray())
158 return Dest->isArray();
159 if (MapKey.isString() && MapKey.getString() == "foz" &&
160 Dest->getKind() == Type::Int && Src.getKind() == Type::Int) {
161 *Dest = Src.getDocument()->getNode(Dest->getInt() | Src.getInt());
162 return true;
163 }
164 return false;
165 });
166 ASSERT_TRUE(Ok);
167 ASSERT_EQ(M.size(), 5u);
168 FooS = M["foo"];
169 ASSERT_EQ(FooS.getKind(), Type::Int);
170 ASSERT_EQ(FooS.getInt(), 1);
171 BarS = M["bar"];
172 ASSERT_EQ(BarS.getKind(), Type::Int);
173 ASSERT_EQ(BarS.getInt(), 2);
174 FozS = M["foz"];
175 ASSERT_EQ(FozS.getKind(), Type::Int);
176 ASSERT_EQ(FozS.getInt(), 7);
177 BazS = M["baz"];
178 ASSERT_EQ(BazS.getKind(), Type::Int);
179 ASSERT_EQ(BazS.getInt(), 4);
180 auto BayS = M["bay"];
181 ASSERT_EQ(BayS.getKind(), Type::Int);
182 ASSERT_EQ(BayS.getInt(), 8);
183 }
184
TEST(MsgPackDocument,TestWriteInt)185 TEST(MsgPackDocument, TestWriteInt) {
186 Document Doc;
187 Doc.getRoot() = 1;
188 std::string Buffer;
189 Doc.writeToBlob(Buffer);
190 ASSERT_EQ(Buffer, "\x01");
191 }
192
TEST(MsgPackDocument,TestWriteArray)193 TEST(MsgPackDocument, TestWriteArray) {
194 Document Doc;
195 auto A = Doc.getRoot().getArray(/*Convert=*/true);
196 A.push_back(Doc.getNode(int64_t(1)));
197 A.push_back(Doc.getNode());
198 std::string Buffer;
199 Doc.writeToBlob(Buffer);
200 ASSERT_EQ(Buffer, "\x92\x01\xc0");
201 }
202
TEST(MsgPackDocument,TestWriteMap)203 TEST(MsgPackDocument, TestWriteMap) {
204 Document Doc;
205 auto M = Doc.getRoot().getMap(/*Convert=*/true);
206 M["foo"] = 1;
207 M["bar"] = 2;
208 std::string Buffer;
209 Doc.writeToBlob(Buffer);
210 ASSERT_EQ(Buffer, "\x82\xa3"
211 "bar"
212 "\x02\xa3"
213 "foo"
214 "\x01");
215 }
216
TEST(MsgPackDocument,TestOutputYAMLArray)217 TEST(MsgPackDocument, TestOutputYAMLArray) {
218 Document Doc;
219 auto A = Doc.getRoot().getArray(/*Convert=*/true);
220 A.push_back(Doc.getNode(int64_t(1)));
221 A.push_back(Doc.getNode(int64_t(2)));
222 std::string Buffer;
223 raw_string_ostream OStream(Buffer);
224 Doc.toYAML(OStream);
225 ASSERT_EQ(OStream.str(), "---\n- 1\n- 2\n...\n");
226 }
227
TEST(MsgPackDocument,TestInputYAMLArray)228 TEST(MsgPackDocument, TestInputYAMLArray) {
229 Document Doc;
230 bool Ok = Doc.fromYAML("---\n- !int 0x1\n- !str 2\n...\n");
231 ASSERT_TRUE(Ok);
232 ASSERT_EQ(Doc.getRoot().getKind(), Type::Array);
233 auto A = Doc.getRoot().getArray();
234 ASSERT_EQ(A.size(), 2u);
235 auto SI = A[0];
236 ASSERT_EQ(SI.getKind(), Type::UInt);
237 ASSERT_EQ(SI.getUInt(), 1u);
238 auto SS = A[1];
239 ASSERT_EQ(SS.getKind(), Type::String);
240 ASSERT_EQ(SS.getString(), "2");
241 }
242
TEST(MsgPackDocument,TestOutputYAMLMap)243 TEST(MsgPackDocument, TestOutputYAMLMap) {
244 Document Doc;
245 auto M = Doc.getRoot().getMap(/*Convert=*/true);
246 M["foo"] = 1;
247 M["bar"] = 2U;
248 auto N = Doc.getMapNode();
249 M["qux"] = N;
250 N["baz"] = true;
251 std::string Buffer;
252 raw_string_ostream OStream(Buffer);
253 Doc.toYAML(OStream);
254 ASSERT_EQ(OStream.str(), "---\n"
255 "bar: 2\n"
256 "foo: 1\n"
257 "qux:\n"
258 " baz: true\n"
259 "...\n");
260 }
261
TEST(MsgPackDocument,TestOutputYAMLMapWithErase)262 TEST(MsgPackDocument, TestOutputYAMLMapWithErase) {
263 Document Doc;
264 auto M = Doc.getRoot().getMap(/*Convert=*/true);
265 M["foo"] = 1;
266 M["bar"] = 2U;
267 auto N = Doc.getMapNode();
268 M["qux"] = N;
269 N["baz"] = true;
270 M.erase(Doc.getNode("bar"));
271 std::string Buffer;
272 raw_string_ostream OStream(Buffer);
273 Doc.toYAML(OStream);
274 ASSERT_EQ(OStream.str(), "---\n"
275 "foo: 1\n"
276 "qux:\n"
277 " baz: true\n"
278 "...\n");
279 }
280
TEST(MsgPackDocument,TestOutputYAMLMapHex)281 TEST(MsgPackDocument, TestOutputYAMLMapHex) {
282 Document Doc;
283 Doc.setHexMode();
284 auto M = Doc.getRoot().getMap(/*Convert=*/true);
285 M["foo"] = 1;
286 M["bar"] = 2U;
287 auto N = Doc.getMapNode();
288 M["qux"] = N;
289 N["baz"] = true;
290 std::string Buffer;
291 raw_string_ostream OStream(Buffer);
292 Doc.toYAML(OStream);
293 ASSERT_EQ(OStream.str(), "---\n"
294 "bar: 0x2\n"
295 "foo: 1\n"
296 "qux:\n"
297 " baz: true\n"
298 "...\n");
299 }
300
TEST(MsgPackDocument,TestInputYAMLMap)301 TEST(MsgPackDocument, TestInputYAMLMap) {
302 Document Doc;
303 bool Ok = Doc.fromYAML("---\nfoo: !int 0x1\nbaz: !str 2\n...\n");
304 ASSERT_TRUE(Ok);
305 ASSERT_EQ(Doc.getRoot().getKind(), Type::Map);
306 auto M = Doc.getRoot().getMap();
307 ASSERT_EQ(M.size(), 2u);
308 auto SI = M["foo"];
309 ASSERT_EQ(SI.getKind(), Type::UInt);
310 ASSERT_EQ(SI.getUInt(), 1u);
311 auto SS = M["baz"];
312 ASSERT_EQ(SS.getKind(), Type::String);
313 ASSERT_EQ(SS.getString(), "2");
314 }
315