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