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, 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 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 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 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 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 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 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 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 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 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 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 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 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 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