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