1 //===- unittest/Support/YAMLIOTest.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/ADT/SmallString.h" 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/Support/Casting.h" 13 #include "llvm/Support/Format.h" 14 #include "llvm/Support/YAMLTraits.h" 15 #include "gtest/gtest.h" 16 17 18 using llvm::yaml::Input; 19 using llvm::yaml::Output; 20 using llvm::yaml::IO; 21 using llvm::yaml::MappingTraits; 22 using llvm::yaml::MappingNormalization; 23 using llvm::yaml::ScalarTraits; 24 using llvm::yaml::Hex8; 25 using llvm::yaml::Hex16; 26 using llvm::yaml::Hex32; 27 using llvm::yaml::Hex64; 28 29 30 31 32 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { 33 } 34 35 36 37 //===----------------------------------------------------------------------===// 38 // Test MappingTraits 39 //===----------------------------------------------------------------------===// 40 41 struct FooBar { 42 int foo; 43 int bar; 44 }; 45 typedef std::vector<FooBar> FooBarSequence; 46 47 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar) 48 49 50 namespace llvm { 51 namespace yaml { 52 template <> 53 struct MappingTraits<FooBar> { 54 static void mapping(IO &io, FooBar& fb) { 55 io.mapRequired("foo", fb.foo); 56 io.mapRequired("bar", fb.bar); 57 } 58 }; 59 } 60 } 61 62 63 // 64 // Test the reading of a yaml mapping 65 // 66 TEST(YAMLIO, TestMapRead) { 67 FooBar doc; 68 { 69 Input yin("---\nfoo: 3\nbar: 5\n...\n"); 70 yin >> doc; 71 72 EXPECT_FALSE(yin.error()); 73 EXPECT_EQ(doc.foo, 3); 74 EXPECT_EQ(doc.bar, 5); 75 } 76 77 { 78 Input yin("{foo: 3, bar: 5}"); 79 yin >> doc; 80 81 EXPECT_FALSE(yin.error()); 82 EXPECT_EQ(doc.foo, 3); 83 EXPECT_EQ(doc.bar, 5); 84 } 85 } 86 87 // 88 // Test the reading of a yaml sequence of mappings 89 // 90 TEST(YAMLIO, TestSequenceMapRead) { 91 FooBarSequence seq; 92 Input yin("---\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n"); 93 yin >> seq; 94 95 EXPECT_FALSE(yin.error()); 96 EXPECT_EQ(seq.size(), 2UL); 97 FooBar& map1 = seq[0]; 98 FooBar& map2 = seq[1]; 99 EXPECT_EQ(map1.foo, 3); 100 EXPECT_EQ(map1.bar, 5); 101 EXPECT_EQ(map2.foo, 7); 102 EXPECT_EQ(map2.bar, 9); 103 } 104 105 106 // 107 // Test writing then reading back a sequence of mappings 108 // 109 TEST(YAMLIO, TestSequenceMapWriteAndRead) { 110 std::string intermediate; 111 { 112 FooBar entry1; 113 entry1.foo = 10; 114 entry1.bar = -3; 115 FooBar entry2; 116 entry2.foo = 257; 117 entry2.bar = 0; 118 FooBarSequence seq; 119 seq.push_back(entry1); 120 seq.push_back(entry2); 121 122 llvm::raw_string_ostream ostr(intermediate); 123 Output yout(ostr); 124 yout << seq; 125 } 126 127 { 128 Input yin(intermediate); 129 FooBarSequence seq2; 130 yin >> seq2; 131 132 EXPECT_FALSE(yin.error()); 133 EXPECT_EQ(seq2.size(), 2UL); 134 FooBar& map1 = seq2[0]; 135 FooBar& map2 = seq2[1]; 136 EXPECT_EQ(map1.foo, 10); 137 EXPECT_EQ(map1.bar, -3); 138 EXPECT_EQ(map2.foo, 257); 139 EXPECT_EQ(map2.bar, 0); 140 } 141 } 142 143 144 //===----------------------------------------------------------------------===// 145 // Test built-in types 146 //===----------------------------------------------------------------------===// 147 148 struct BuiltInTypes { 149 llvm::StringRef str; 150 std::string stdstr; 151 uint64_t u64; 152 uint32_t u32; 153 uint16_t u16; 154 uint8_t u8; 155 bool b; 156 int64_t s64; 157 int32_t s32; 158 int16_t s16; 159 int8_t s8; 160 float f; 161 double d; 162 Hex8 h8; 163 Hex16 h16; 164 Hex32 h32; 165 Hex64 h64; 166 }; 167 168 namespace llvm { 169 namespace yaml { 170 template <> 171 struct MappingTraits<BuiltInTypes> { 172 static void mapping(IO &io, BuiltInTypes& bt) { 173 io.mapRequired("str", bt.str); 174 io.mapRequired("stdstr", bt.stdstr); 175 io.mapRequired("u64", bt.u64); 176 io.mapRequired("u32", bt.u32); 177 io.mapRequired("u16", bt.u16); 178 io.mapRequired("u8", bt.u8); 179 io.mapRequired("b", bt.b); 180 io.mapRequired("s64", bt.s64); 181 io.mapRequired("s32", bt.s32); 182 io.mapRequired("s16", bt.s16); 183 io.mapRequired("s8", bt.s8); 184 io.mapRequired("f", bt.f); 185 io.mapRequired("d", bt.d); 186 io.mapRequired("h8", bt.h8); 187 io.mapRequired("h16", bt.h16); 188 io.mapRequired("h32", bt.h32); 189 io.mapRequired("h64", bt.h64); 190 } 191 }; 192 } 193 } 194 195 196 // 197 // Test the reading of all built-in scalar conversions 198 // 199 TEST(YAMLIO, TestReadBuiltInTypes) { 200 BuiltInTypes map; 201 Input yin("---\n" 202 "str: hello there\n" 203 "stdstr: hello where?\n" 204 "u64: 5000000000\n" 205 "u32: 4000000000\n" 206 "u16: 65000\n" 207 "u8: 255\n" 208 "b: false\n" 209 "s64: -5000000000\n" 210 "s32: -2000000000\n" 211 "s16: -32000\n" 212 "s8: -127\n" 213 "f: 137.125\n" 214 "d: -2.8625\n" 215 "h8: 0xFF\n" 216 "h16: 0x8765\n" 217 "h32: 0xFEDCBA98\n" 218 "h64: 0xFEDCBA9876543210\n" 219 "...\n"); 220 yin >> map; 221 222 EXPECT_FALSE(yin.error()); 223 EXPECT_TRUE(map.str.equals("hello there")); 224 EXPECT_TRUE(map.stdstr == "hello where?"); 225 EXPECT_EQ(map.u64, 5000000000ULL); 226 EXPECT_EQ(map.u32, 4000000000U); 227 EXPECT_EQ(map.u16, 65000); 228 EXPECT_EQ(map.u8, 255); 229 EXPECT_EQ(map.b, false); 230 EXPECT_EQ(map.s64, -5000000000LL); 231 EXPECT_EQ(map.s32, -2000000000L); 232 EXPECT_EQ(map.s16, -32000); 233 EXPECT_EQ(map.s8, -127); 234 EXPECT_EQ(map.f, 137.125); 235 EXPECT_EQ(map.d, -2.8625); 236 EXPECT_EQ(map.h8, Hex8(255)); 237 EXPECT_EQ(map.h16, Hex16(0x8765)); 238 EXPECT_EQ(map.h32, Hex32(0xFEDCBA98)); 239 EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL)); 240 } 241 242 243 // 244 // Test writing then reading back all built-in scalar types 245 // 246 TEST(YAMLIO, TestReadWriteBuiltInTypes) { 247 std::string intermediate; 248 { 249 BuiltInTypes map; 250 map.str = "one two"; 251 map.stdstr = "three four"; 252 map.u64 = 6000000000ULL; 253 map.u32 = 3000000000U; 254 map.u16 = 50000; 255 map.u8 = 254; 256 map.b = true; 257 map.s64 = -6000000000LL; 258 map.s32 = -2000000000; 259 map.s16 = -32000; 260 map.s8 = -128; 261 map.f = 3.25; 262 map.d = -2.8625; 263 map.h8 = 254; 264 map.h16 = 50000; 265 map.h32 = 3000000000U; 266 map.h64 = 6000000000LL; 267 268 llvm::raw_string_ostream ostr(intermediate); 269 Output yout(ostr); 270 yout << map; 271 } 272 273 { 274 Input yin(intermediate); 275 BuiltInTypes map; 276 yin >> map; 277 278 EXPECT_FALSE(yin.error()); 279 EXPECT_TRUE(map.str.equals("one two")); 280 EXPECT_TRUE(map.stdstr == "three four"); 281 EXPECT_EQ(map.u64, 6000000000ULL); 282 EXPECT_EQ(map.u32, 3000000000U); 283 EXPECT_EQ(map.u16, 50000); 284 EXPECT_EQ(map.u8, 254); 285 EXPECT_EQ(map.b, true); 286 EXPECT_EQ(map.s64, -6000000000LL); 287 EXPECT_EQ(map.s32, -2000000000L); 288 EXPECT_EQ(map.s16, -32000); 289 EXPECT_EQ(map.s8, -128); 290 EXPECT_EQ(map.f, 3.25); 291 EXPECT_EQ(map.d, -2.8625); 292 EXPECT_EQ(map.h8, Hex8(254)); 293 EXPECT_EQ(map.h16, Hex16(50000)); 294 EXPECT_EQ(map.h32, Hex32(3000000000U)); 295 EXPECT_EQ(map.h64, Hex64(6000000000LL)); 296 } 297 } 298 299 struct StringTypes { 300 llvm::StringRef str1; 301 llvm::StringRef str2; 302 llvm::StringRef str3; 303 llvm::StringRef str4; 304 llvm::StringRef str5; 305 llvm::StringRef str6; 306 llvm::StringRef str7; 307 llvm::StringRef str8; 308 llvm::StringRef str9; 309 llvm::StringRef str10; 310 llvm::StringRef str11; 311 std::string stdstr1; 312 std::string stdstr2; 313 std::string stdstr3; 314 std::string stdstr4; 315 std::string stdstr5; 316 std::string stdstr6; 317 std::string stdstr7; 318 std::string stdstr8; 319 std::string stdstr9; 320 std::string stdstr10; 321 std::string stdstr11; 322 }; 323 324 namespace llvm { 325 namespace yaml { 326 template <> 327 struct MappingTraits<StringTypes> { 328 static void mapping(IO &io, StringTypes& st) { 329 io.mapRequired("str1", st.str1); 330 io.mapRequired("str2", st.str2); 331 io.mapRequired("str3", st.str3); 332 io.mapRequired("str4", st.str4); 333 io.mapRequired("str5", st.str5); 334 io.mapRequired("str6", st.str6); 335 io.mapRequired("str7", st.str7); 336 io.mapRequired("str8", st.str8); 337 io.mapRequired("str9", st.str9); 338 io.mapRequired("str10", st.str10); 339 io.mapRequired("str11", st.str11); 340 io.mapRequired("stdstr1", st.stdstr1); 341 io.mapRequired("stdstr2", st.stdstr2); 342 io.mapRequired("stdstr3", st.stdstr3); 343 io.mapRequired("stdstr4", st.stdstr4); 344 io.mapRequired("stdstr5", st.stdstr5); 345 io.mapRequired("stdstr6", st.stdstr6); 346 io.mapRequired("stdstr7", st.stdstr7); 347 io.mapRequired("stdstr8", st.stdstr8); 348 io.mapRequired("stdstr9", st.stdstr9); 349 io.mapRequired("stdstr10", st.stdstr10); 350 io.mapRequired("stdstr11", st.stdstr11); 351 } 352 }; 353 } 354 } 355 356 TEST(YAMLIO, TestReadWriteStringTypes) { 357 std::string intermediate; 358 { 359 StringTypes map; 360 map.str1 = "'aaa"; 361 map.str2 = "\"bbb"; 362 map.str3 = "`ccc"; 363 map.str4 = "@ddd"; 364 map.str5 = ""; 365 map.str6 = "0000000004000000"; 366 map.str7 = "true"; 367 map.str8 = "FALSE"; 368 map.str9 = "~"; 369 map.str10 = "0.2e20"; 370 map.str11 = "0x30"; 371 map.stdstr1 = "'eee"; 372 map.stdstr2 = "\"fff"; 373 map.stdstr3 = "`ggg"; 374 map.stdstr4 = "@hhh"; 375 map.stdstr5 = ""; 376 map.stdstr6 = "0000000004000000"; 377 map.stdstr7 = "true"; 378 map.stdstr8 = "FALSE"; 379 map.stdstr9 = "~"; 380 map.stdstr10 = "0.2e20"; 381 map.stdstr11 = "0x30"; 382 383 llvm::raw_string_ostream ostr(intermediate); 384 Output yout(ostr); 385 yout << map; 386 } 387 388 llvm::StringRef flowOut(intermediate); 389 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa")); 390 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'")); 391 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); 392 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); 393 EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); 394 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n")); 395 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n")); 396 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n")); 397 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n")); 398 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n")); 399 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n")); 400 EXPECT_NE(std::string::npos, flowOut.find("'''eee")); 401 EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); 402 EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); 403 EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); 404 EXPECT_NE(std::string::npos, flowOut.find("''\n")); 405 EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n")); 406 407 { 408 Input yin(intermediate); 409 StringTypes map; 410 yin >> map; 411 412 EXPECT_FALSE(yin.error()); 413 EXPECT_TRUE(map.str1.equals("'aaa")); 414 EXPECT_TRUE(map.str2.equals("\"bbb")); 415 EXPECT_TRUE(map.str3.equals("`ccc")); 416 EXPECT_TRUE(map.str4.equals("@ddd")); 417 EXPECT_TRUE(map.str5.equals("")); 418 EXPECT_TRUE(map.str6.equals("0000000004000000")); 419 EXPECT_TRUE(map.stdstr1 == "'eee"); 420 EXPECT_TRUE(map.stdstr2 == "\"fff"); 421 EXPECT_TRUE(map.stdstr3 == "`ggg"); 422 EXPECT_TRUE(map.stdstr4 == "@hhh"); 423 EXPECT_TRUE(map.stdstr5 == ""); 424 EXPECT_TRUE(map.stdstr6 == "0000000004000000"); 425 } 426 } 427 428 //===----------------------------------------------------------------------===// 429 // Test ScalarEnumerationTraits 430 //===----------------------------------------------------------------------===// 431 432 enum Colors { 433 cRed, 434 cBlue, 435 cGreen, 436 cYellow 437 }; 438 439 struct ColorMap { 440 Colors c1; 441 Colors c2; 442 Colors c3; 443 Colors c4; 444 Colors c5; 445 Colors c6; 446 }; 447 448 namespace llvm { 449 namespace yaml { 450 template <> 451 struct ScalarEnumerationTraits<Colors> { 452 static void enumeration(IO &io, Colors &value) { 453 io.enumCase(value, "red", cRed); 454 io.enumCase(value, "blue", cBlue); 455 io.enumCase(value, "green", cGreen); 456 io.enumCase(value, "yellow",cYellow); 457 } 458 }; 459 template <> 460 struct MappingTraits<ColorMap> { 461 static void mapping(IO &io, ColorMap& c) { 462 io.mapRequired("c1", c.c1); 463 io.mapRequired("c2", c.c2); 464 io.mapRequired("c3", c.c3); 465 io.mapOptional("c4", c.c4, cBlue); // supplies default 466 io.mapOptional("c5", c.c5, cYellow); // supplies default 467 io.mapOptional("c6", c.c6, cRed); // supplies default 468 } 469 }; 470 } 471 } 472 473 474 // 475 // Test reading enumerated scalars 476 // 477 TEST(YAMLIO, TestEnumRead) { 478 ColorMap map; 479 Input yin("---\n" 480 "c1: blue\n" 481 "c2: red\n" 482 "c3: green\n" 483 "c5: yellow\n" 484 "...\n"); 485 yin >> map; 486 487 EXPECT_FALSE(yin.error()); 488 EXPECT_EQ(cBlue, map.c1); 489 EXPECT_EQ(cRed, map.c2); 490 EXPECT_EQ(cGreen, map.c3); 491 EXPECT_EQ(cBlue, map.c4); // tests default 492 EXPECT_EQ(cYellow,map.c5); // tests overridden 493 EXPECT_EQ(cRed, map.c6); // tests default 494 } 495 496 497 498 //===----------------------------------------------------------------------===// 499 // Test ScalarBitSetTraits 500 //===----------------------------------------------------------------------===// 501 502 enum MyFlags { 503 flagNone = 0, 504 flagBig = 1 << 0, 505 flagFlat = 1 << 1, 506 flagRound = 1 << 2, 507 flagPointy = 1 << 3 508 }; 509 inline MyFlags operator|(MyFlags a, MyFlags b) { 510 return static_cast<MyFlags>( 511 static_cast<uint32_t>(a) | static_cast<uint32_t>(b)); 512 } 513 514 struct FlagsMap { 515 MyFlags f1; 516 MyFlags f2; 517 MyFlags f3; 518 MyFlags f4; 519 }; 520 521 522 namespace llvm { 523 namespace yaml { 524 template <> 525 struct ScalarBitSetTraits<MyFlags> { 526 static void bitset(IO &io, MyFlags &value) { 527 io.bitSetCase(value, "big", flagBig); 528 io.bitSetCase(value, "flat", flagFlat); 529 io.bitSetCase(value, "round", flagRound); 530 io.bitSetCase(value, "pointy",flagPointy); 531 } 532 }; 533 template <> 534 struct MappingTraits<FlagsMap> { 535 static void mapping(IO &io, FlagsMap& c) { 536 io.mapRequired("f1", c.f1); 537 io.mapRequired("f2", c.f2); 538 io.mapRequired("f3", c.f3); 539 io.mapOptional("f4", c.f4, MyFlags(flagRound)); 540 } 541 }; 542 } 543 } 544 545 546 // 547 // Test reading flow sequence representing bit-mask values 548 // 549 TEST(YAMLIO, TestFlagsRead) { 550 FlagsMap map; 551 Input yin("---\n" 552 "f1: [ big ]\n" 553 "f2: [ round, flat ]\n" 554 "f3: []\n" 555 "...\n"); 556 yin >> map; 557 558 EXPECT_FALSE(yin.error()); 559 EXPECT_EQ(flagBig, map.f1); 560 EXPECT_EQ(flagRound|flagFlat, map.f2); 561 EXPECT_EQ(flagNone, map.f3); // check empty set 562 EXPECT_EQ(flagRound, map.f4); // check optional key 563 } 564 565 566 // 567 // Test writing then reading back bit-mask values 568 // 569 TEST(YAMLIO, TestReadWriteFlags) { 570 std::string intermediate; 571 { 572 FlagsMap map; 573 map.f1 = flagBig; 574 map.f2 = flagRound | flagFlat; 575 map.f3 = flagNone; 576 map.f4 = flagNone; 577 578 llvm::raw_string_ostream ostr(intermediate); 579 Output yout(ostr); 580 yout << map; 581 } 582 583 { 584 Input yin(intermediate); 585 FlagsMap map2; 586 yin >> map2; 587 588 EXPECT_FALSE(yin.error()); 589 EXPECT_EQ(flagBig, map2.f1); 590 EXPECT_EQ(flagRound|flagFlat, map2.f2); 591 EXPECT_EQ(flagNone, map2.f3); 592 //EXPECT_EQ(flagRound, map2.f4); // check optional key 593 } 594 } 595 596 597 598 //===----------------------------------------------------------------------===// 599 // Test ScalarTraits 600 //===----------------------------------------------------------------------===// 601 602 struct MyCustomType { 603 int length; 604 int width; 605 }; 606 607 struct MyCustomTypeMap { 608 MyCustomType f1; 609 MyCustomType f2; 610 int f3; 611 }; 612 613 614 namespace llvm { 615 namespace yaml { 616 template <> 617 struct MappingTraits<MyCustomTypeMap> { 618 static void mapping(IO &io, MyCustomTypeMap& s) { 619 io.mapRequired("f1", s.f1); 620 io.mapRequired("f2", s.f2); 621 io.mapRequired("f3", s.f3); 622 } 623 }; 624 // MyCustomType is formatted as a yaml scalar. A value of 625 // {length=3, width=4} would be represented in yaml as "3 by 4". 626 template<> 627 struct ScalarTraits<MyCustomType> { 628 static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) { 629 out << llvm::format("%d by %d", value.length, value.width); 630 } 631 static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) { 632 size_t byStart = scalar.find("by"); 633 if ( byStart != StringRef::npos ) { 634 StringRef lenStr = scalar.slice(0, byStart); 635 lenStr = lenStr.rtrim(); 636 if ( lenStr.getAsInteger(0, value.length) ) { 637 return "malformed length"; 638 } 639 StringRef widthStr = scalar.drop_front(byStart+2); 640 widthStr = widthStr.ltrim(); 641 if ( widthStr.getAsInteger(0, value.width) ) { 642 return "malformed width"; 643 } 644 return StringRef(); 645 } 646 else { 647 return "malformed by"; 648 } 649 } 650 static bool mustQuote(StringRef) { return true; } 651 }; 652 } 653 } 654 655 656 // 657 // Test writing then reading back custom values 658 // 659 TEST(YAMLIO, TestReadWriteMyCustomType) { 660 std::string intermediate; 661 { 662 MyCustomTypeMap map; 663 map.f1.length = 1; 664 map.f1.width = 4; 665 map.f2.length = 100; 666 map.f2.width = 400; 667 map.f3 = 10; 668 669 llvm::raw_string_ostream ostr(intermediate); 670 Output yout(ostr); 671 yout << map; 672 } 673 674 { 675 Input yin(intermediate); 676 MyCustomTypeMap map2; 677 yin >> map2; 678 679 EXPECT_FALSE(yin.error()); 680 EXPECT_EQ(1, map2.f1.length); 681 EXPECT_EQ(4, map2.f1.width); 682 EXPECT_EQ(100, map2.f2.length); 683 EXPECT_EQ(400, map2.f2.width); 684 EXPECT_EQ(10, map2.f3); 685 } 686 } 687 688 689 //===----------------------------------------------------------------------===// 690 // Test flow sequences 691 //===----------------------------------------------------------------------===// 692 693 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber) 694 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber) 695 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef) 696 697 namespace llvm { 698 namespace yaml { 699 template<> 700 struct ScalarTraits<MyNumber> { 701 static void output(const MyNumber &value, void *, llvm::raw_ostream &out) { 702 out << value; 703 } 704 705 static StringRef input(StringRef scalar, void *, MyNumber &value) { 706 long long n; 707 if ( getAsSignedInteger(scalar, 0, n) ) 708 return "invalid number"; 709 value = n; 710 return StringRef(); 711 } 712 713 static bool mustQuote(StringRef) { return false; } 714 }; 715 } 716 } 717 718 struct NameAndNumbers { 719 llvm::StringRef name; 720 std::vector<llvm::StringRef> strings; 721 std::vector<MyNumber> single; 722 std::vector<MyNumber> numbers; 723 }; 724 725 namespace llvm { 726 namespace yaml { 727 template <> 728 struct MappingTraits<NameAndNumbers> { 729 static void mapping(IO &io, NameAndNumbers& nn) { 730 io.mapRequired("name", nn.name); 731 io.mapRequired("strings", nn.strings); 732 io.mapRequired("single", nn.single); 733 io.mapRequired("numbers", nn.numbers); 734 } 735 }; 736 } 737 } 738 739 740 // 741 // Test writing then reading back custom values 742 // 743 TEST(YAMLIO, TestReadWriteMyFlowSequence) { 744 std::string intermediate; 745 { 746 NameAndNumbers map; 747 map.name = "hello"; 748 map.strings.push_back(llvm::StringRef("one")); 749 map.strings.push_back(llvm::StringRef("two")); 750 map.single.push_back(1); 751 map.numbers.push_back(10); 752 map.numbers.push_back(-30); 753 map.numbers.push_back(1024); 754 755 llvm::raw_string_ostream ostr(intermediate); 756 Output yout(ostr); 757 yout << map; 758 759 // Verify sequences were written in flow style 760 ostr.flush(); 761 llvm::StringRef flowOut(intermediate); 762 EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two")); 763 EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024")); 764 } 765 766 { 767 Input yin(intermediate); 768 NameAndNumbers map2; 769 yin >> map2; 770 771 EXPECT_FALSE(yin.error()); 772 EXPECT_TRUE(map2.name.equals("hello")); 773 EXPECT_EQ(map2.strings.size(), 2UL); 774 EXPECT_TRUE(map2.strings[0].equals("one")); 775 EXPECT_TRUE(map2.strings[1].equals("two")); 776 EXPECT_EQ(map2.single.size(), 1UL); 777 EXPECT_EQ(1, map2.single[0]); 778 EXPECT_EQ(map2.numbers.size(), 3UL); 779 EXPECT_EQ(10, map2.numbers[0]); 780 EXPECT_EQ(-30, map2.numbers[1]); 781 EXPECT_EQ(1024, map2.numbers[2]); 782 } 783 } 784 785 786 //===----------------------------------------------------------------------===// 787 // Test normalizing/denormalizing 788 //===----------------------------------------------------------------------===// 789 790 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds) 791 792 typedef std::vector<TotalSeconds> SecondsSequence; 793 794 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds) 795 796 797 namespace llvm { 798 namespace yaml { 799 template <> 800 struct MappingTraits<TotalSeconds> { 801 802 class NormalizedSeconds { 803 public: 804 NormalizedSeconds(IO &io) 805 : hours(0), minutes(0), seconds(0) { 806 } 807 NormalizedSeconds(IO &, TotalSeconds &secs) 808 : hours(secs/3600), 809 minutes((secs - (hours*3600))/60), 810 seconds(secs % 60) { 811 } 812 TotalSeconds denormalize(IO &) { 813 return TotalSeconds(hours*3600 + minutes*60 + seconds); 814 } 815 816 uint32_t hours; 817 uint8_t minutes; 818 uint8_t seconds; 819 }; 820 821 static void mapping(IO &io, TotalSeconds &secs) { 822 MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs); 823 824 io.mapOptional("hours", keys->hours, (uint32_t)0); 825 io.mapOptional("minutes", keys->minutes, (uint8_t)0); 826 io.mapRequired("seconds", keys->seconds); 827 } 828 }; 829 } 830 } 831 832 833 // 834 // Test the reading of a yaml sequence of mappings 835 // 836 TEST(YAMLIO, TestReadMySecondsSequence) { 837 SecondsSequence seq; 838 Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n"); 839 yin >> seq; 840 841 EXPECT_FALSE(yin.error()); 842 EXPECT_EQ(seq.size(), 2UL); 843 EXPECT_EQ(seq[0], 3605U); 844 EXPECT_EQ(seq[1], 59U); 845 } 846 847 848 // 849 // Test writing then reading back custom values 850 // 851 TEST(YAMLIO, TestReadWriteMySecondsSequence) { 852 std::string intermediate; 853 { 854 SecondsSequence seq; 855 seq.push_back(4000); 856 seq.push_back(500); 857 seq.push_back(59); 858 859 llvm::raw_string_ostream ostr(intermediate); 860 Output yout(ostr); 861 yout << seq; 862 } 863 { 864 Input yin(intermediate); 865 SecondsSequence seq2; 866 yin >> seq2; 867 868 EXPECT_FALSE(yin.error()); 869 EXPECT_EQ(seq2.size(), 3UL); 870 EXPECT_EQ(seq2[0], 4000U); 871 EXPECT_EQ(seq2[1], 500U); 872 EXPECT_EQ(seq2[2], 59U); 873 } 874 } 875 876 877 //===----------------------------------------------------------------------===// 878 // Test dynamic typing 879 //===----------------------------------------------------------------------===// 880 881 enum AFlags { 882 a1, 883 a2, 884 a3 885 }; 886 887 enum BFlags { 888 b1, 889 b2, 890 b3 891 }; 892 893 enum Kind { 894 kindA, 895 kindB 896 }; 897 898 struct KindAndFlags { 899 KindAndFlags() : kind(kindA), flags(0) { } 900 KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { } 901 Kind kind; 902 uint32_t flags; 903 }; 904 905 typedef std::vector<KindAndFlags> KindAndFlagsSequence; 906 907 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags) 908 909 namespace llvm { 910 namespace yaml { 911 template <> 912 struct ScalarEnumerationTraits<AFlags> { 913 static void enumeration(IO &io, AFlags &value) { 914 io.enumCase(value, "a1", a1); 915 io.enumCase(value, "a2", a2); 916 io.enumCase(value, "a3", a3); 917 } 918 }; 919 template <> 920 struct ScalarEnumerationTraits<BFlags> { 921 static void enumeration(IO &io, BFlags &value) { 922 io.enumCase(value, "b1", b1); 923 io.enumCase(value, "b2", b2); 924 io.enumCase(value, "b3", b3); 925 } 926 }; 927 template <> 928 struct ScalarEnumerationTraits<Kind> { 929 static void enumeration(IO &io, Kind &value) { 930 io.enumCase(value, "A", kindA); 931 io.enumCase(value, "B", kindB); 932 } 933 }; 934 template <> 935 struct MappingTraits<KindAndFlags> { 936 static void mapping(IO &io, KindAndFlags& kf) { 937 io.mapRequired("kind", kf.kind); 938 // Type of "flags" field varies depending on "kind" field. 939 // Use memcpy here to avoid breaking strict aliasing rules. 940 if (kf.kind == kindA) { 941 AFlags aflags = static_cast<AFlags>(kf.flags); 942 io.mapRequired("flags", aflags); 943 kf.flags = aflags; 944 } else { 945 BFlags bflags = static_cast<BFlags>(kf.flags); 946 io.mapRequired("flags", bflags); 947 kf.flags = bflags; 948 } 949 } 950 }; 951 } 952 } 953 954 955 // 956 // Test the reading of a yaml sequence dynamic types 957 // 958 TEST(YAMLIO, TestReadKindAndFlagsSequence) { 959 KindAndFlagsSequence seq; 960 Input yin("---\n - kind: A\n flags: a2\n - kind: B\n flags: b1\n...\n"); 961 yin >> seq; 962 963 EXPECT_FALSE(yin.error()); 964 EXPECT_EQ(seq.size(), 2UL); 965 EXPECT_EQ(seq[0].kind, kindA); 966 EXPECT_EQ(seq[0].flags, (uint32_t)a2); 967 EXPECT_EQ(seq[1].kind, kindB); 968 EXPECT_EQ(seq[1].flags, (uint32_t)b1); 969 } 970 971 // 972 // Test writing then reading back dynamic types 973 // 974 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) { 975 std::string intermediate; 976 { 977 KindAndFlagsSequence seq; 978 seq.push_back(KindAndFlags(kindA,a1)); 979 seq.push_back(KindAndFlags(kindB,b1)); 980 seq.push_back(KindAndFlags(kindA,a2)); 981 seq.push_back(KindAndFlags(kindB,b2)); 982 seq.push_back(KindAndFlags(kindA,a3)); 983 984 llvm::raw_string_ostream ostr(intermediate); 985 Output yout(ostr); 986 yout << seq; 987 } 988 { 989 Input yin(intermediate); 990 KindAndFlagsSequence seq2; 991 yin >> seq2; 992 993 EXPECT_FALSE(yin.error()); 994 EXPECT_EQ(seq2.size(), 5UL); 995 EXPECT_EQ(seq2[0].kind, kindA); 996 EXPECT_EQ(seq2[0].flags, (uint32_t)a1); 997 EXPECT_EQ(seq2[1].kind, kindB); 998 EXPECT_EQ(seq2[1].flags, (uint32_t)b1); 999 EXPECT_EQ(seq2[2].kind, kindA); 1000 EXPECT_EQ(seq2[2].flags, (uint32_t)a2); 1001 EXPECT_EQ(seq2[3].kind, kindB); 1002 EXPECT_EQ(seq2[3].flags, (uint32_t)b2); 1003 EXPECT_EQ(seq2[4].kind, kindA); 1004 EXPECT_EQ(seq2[4].flags, (uint32_t)a3); 1005 } 1006 } 1007 1008 1009 //===----------------------------------------------------------------------===// 1010 // Test document list 1011 //===----------------------------------------------------------------------===// 1012 1013 struct FooBarMap { 1014 int foo; 1015 int bar; 1016 }; 1017 typedef std::vector<FooBarMap> FooBarMapDocumentList; 1018 1019 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap) 1020 1021 1022 namespace llvm { 1023 namespace yaml { 1024 template <> 1025 struct MappingTraits<FooBarMap> { 1026 static void mapping(IO &io, FooBarMap& fb) { 1027 io.mapRequired("foo", fb.foo); 1028 io.mapRequired("bar", fb.bar); 1029 } 1030 }; 1031 } 1032 } 1033 1034 1035 // 1036 // Test the reading of a yaml mapping 1037 // 1038 TEST(YAMLIO, TestDocRead) { 1039 FooBarMap doc; 1040 Input yin("---\nfoo: 3\nbar: 5\n...\n"); 1041 yin >> doc; 1042 1043 EXPECT_FALSE(yin.error()); 1044 EXPECT_EQ(doc.foo, 3); 1045 EXPECT_EQ(doc.bar,5); 1046 } 1047 1048 1049 1050 // 1051 // Test writing then reading back a sequence of mappings 1052 // 1053 TEST(YAMLIO, TestSequenceDocListWriteAndRead) { 1054 std::string intermediate; 1055 { 1056 FooBarMap doc1; 1057 doc1.foo = 10; 1058 doc1.bar = -3; 1059 FooBarMap doc2; 1060 doc2.foo = 257; 1061 doc2.bar = 0; 1062 std::vector<FooBarMap> docList; 1063 docList.push_back(doc1); 1064 docList.push_back(doc2); 1065 1066 llvm::raw_string_ostream ostr(intermediate); 1067 Output yout(ostr); 1068 yout << docList; 1069 } 1070 1071 1072 { 1073 Input yin(intermediate); 1074 std::vector<FooBarMap> docList2; 1075 yin >> docList2; 1076 1077 EXPECT_FALSE(yin.error()); 1078 EXPECT_EQ(docList2.size(), 2UL); 1079 FooBarMap& map1 = docList2[0]; 1080 FooBarMap& map2 = docList2[1]; 1081 EXPECT_EQ(map1.foo, 10); 1082 EXPECT_EQ(map1.bar, -3); 1083 EXPECT_EQ(map2.foo, 257); 1084 EXPECT_EQ(map2.bar, 0); 1085 } 1086 } 1087 1088 //===----------------------------------------------------------------------===// 1089 // Test document tags 1090 //===----------------------------------------------------------------------===// 1091 1092 struct MyDouble { 1093 MyDouble() : value(0.0) { } 1094 MyDouble(double x) : value(x) { } 1095 double value; 1096 }; 1097 1098 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble) 1099 1100 1101 namespace llvm { 1102 namespace yaml { 1103 template <> 1104 struct MappingTraits<MyDouble> { 1105 static void mapping(IO &io, MyDouble &d) { 1106 if (io.mapTag("!decimal", true)) { 1107 mappingDecimal(io, d); 1108 } else if (io.mapTag("!fraction")) { 1109 mappingFraction(io, d); 1110 } 1111 } 1112 static void mappingDecimal(IO &io, MyDouble &d) { 1113 io.mapRequired("value", d.value); 1114 } 1115 static void mappingFraction(IO &io, MyDouble &d) { 1116 double num, denom; 1117 io.mapRequired("numerator", num); 1118 io.mapRequired("denominator", denom); 1119 // convert fraction to double 1120 d.value = num/denom; 1121 } 1122 }; 1123 } 1124 } 1125 1126 1127 // 1128 // Test the reading of two different tagged yaml documents. 1129 // 1130 TEST(YAMLIO, TestTaggedDocuments) { 1131 std::vector<MyDouble> docList; 1132 Input yin("--- !decimal\nvalue: 3.0\n" 1133 "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n"); 1134 yin >> docList; 1135 EXPECT_FALSE(yin.error()); 1136 EXPECT_EQ(docList.size(), 2UL); 1137 EXPECT_EQ(docList[0].value, 3.0); 1138 EXPECT_EQ(docList[1].value, 4.5); 1139 } 1140 1141 1142 1143 // 1144 // Test writing then reading back tagged documents 1145 // 1146 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) { 1147 std::string intermediate; 1148 { 1149 MyDouble a(10.25); 1150 MyDouble b(-3.75); 1151 std::vector<MyDouble> docList; 1152 docList.push_back(a); 1153 docList.push_back(b); 1154 1155 llvm::raw_string_ostream ostr(intermediate); 1156 Output yout(ostr); 1157 yout << docList; 1158 } 1159 1160 { 1161 Input yin(intermediate); 1162 std::vector<MyDouble> docList2; 1163 yin >> docList2; 1164 1165 EXPECT_FALSE(yin.error()); 1166 EXPECT_EQ(docList2.size(), 2UL); 1167 EXPECT_EQ(docList2[0].value, 10.25); 1168 EXPECT_EQ(docList2[1].value, -3.75); 1169 } 1170 } 1171 1172 1173 //===----------------------------------------------------------------------===// 1174 // Test mapping validation 1175 //===----------------------------------------------------------------------===// 1176 1177 struct MyValidation { 1178 double value; 1179 }; 1180 1181 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation) 1182 1183 namespace llvm { 1184 namespace yaml { 1185 template <> 1186 struct MappingTraits<MyValidation> { 1187 static void mapping(IO &io, MyValidation &d) { 1188 io.mapRequired("value", d.value); 1189 } 1190 static StringRef validate(IO &io, MyValidation &d) { 1191 if (d.value < 0) 1192 return "negative value"; 1193 return StringRef(); 1194 } 1195 }; 1196 } 1197 } 1198 1199 1200 // 1201 // Test that validate() is called and complains about the negative value. 1202 // 1203 TEST(YAMLIO, TestValidatingInput) { 1204 std::vector<MyValidation> docList; 1205 Input yin("--- \nvalue: 3.0\n" 1206 "--- \nvalue: -1.0\n...\n", 1207 nullptr, suppressErrorMessages); 1208 yin >> docList; 1209 EXPECT_TRUE(!!yin.error()); 1210 } 1211 1212 1213 //===----------------------------------------------------------------------===// 1214 // Test error handling 1215 //===----------------------------------------------------------------------===// 1216 1217 // 1218 // Test error handling of unknown enumerated scalar 1219 // 1220 TEST(YAMLIO, TestColorsReadError) { 1221 ColorMap map; 1222 Input yin("---\n" 1223 "c1: blue\n" 1224 "c2: purple\n" 1225 "c3: green\n" 1226 "...\n", 1227 /*Ctxt=*/nullptr, 1228 suppressErrorMessages); 1229 yin >> map; 1230 EXPECT_TRUE(!!yin.error()); 1231 } 1232 1233 1234 // 1235 // Test error handling of flow sequence with unknown value 1236 // 1237 TEST(YAMLIO, TestFlagsReadError) { 1238 FlagsMap map; 1239 Input yin("---\n" 1240 "f1: [ big ]\n" 1241 "f2: [ round, hollow ]\n" 1242 "f3: []\n" 1243 "...\n", 1244 /*Ctxt=*/nullptr, 1245 suppressErrorMessages); 1246 yin >> map; 1247 1248 EXPECT_TRUE(!!yin.error()); 1249 } 1250 1251 1252 // 1253 // Test error handling reading built-in uint8_t type 1254 // 1255 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t) 1256 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { 1257 std::vector<uint8_t> seq; 1258 Input yin("---\n" 1259 "- 255\n" 1260 "- 0\n" 1261 "- 257\n" 1262 "...\n", 1263 /*Ctxt=*/nullptr, 1264 suppressErrorMessages); 1265 yin >> seq; 1266 1267 EXPECT_TRUE(!!yin.error()); 1268 } 1269 1270 1271 // 1272 // Test error handling reading built-in uint16_t type 1273 // 1274 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t) 1275 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { 1276 std::vector<uint16_t> seq; 1277 Input yin("---\n" 1278 "- 65535\n" 1279 "- 0\n" 1280 "- 66000\n" 1281 "...\n", 1282 /*Ctxt=*/nullptr, 1283 suppressErrorMessages); 1284 yin >> seq; 1285 1286 EXPECT_TRUE(!!yin.error()); 1287 } 1288 1289 1290 // 1291 // Test error handling reading built-in uint32_t type 1292 // 1293 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t) 1294 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { 1295 std::vector<uint32_t> seq; 1296 Input yin("---\n" 1297 "- 4000000000\n" 1298 "- 0\n" 1299 "- 5000000000\n" 1300 "...\n", 1301 /*Ctxt=*/nullptr, 1302 suppressErrorMessages); 1303 yin >> seq; 1304 1305 EXPECT_TRUE(!!yin.error()); 1306 } 1307 1308 1309 // 1310 // Test error handling reading built-in uint64_t type 1311 // 1312 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t) 1313 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { 1314 std::vector<uint64_t> seq; 1315 Input yin("---\n" 1316 "- 18446744073709551615\n" 1317 "- 0\n" 1318 "- 19446744073709551615\n" 1319 "...\n", 1320 /*Ctxt=*/nullptr, 1321 suppressErrorMessages); 1322 yin >> seq; 1323 1324 EXPECT_TRUE(!!yin.error()); 1325 } 1326 1327 1328 // 1329 // Test error handling reading built-in int8_t type 1330 // 1331 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t) 1332 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { 1333 std::vector<int8_t> seq; 1334 Input yin("---\n" 1335 "- -128\n" 1336 "- 0\n" 1337 "- 127\n" 1338 "- 128\n" 1339 "...\n", 1340 /*Ctxt=*/nullptr, 1341 suppressErrorMessages); 1342 yin >> seq; 1343 1344 EXPECT_TRUE(!!yin.error()); 1345 } 1346 1347 // 1348 // Test error handling reading built-in int8_t type 1349 // 1350 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { 1351 std::vector<int8_t> seq; 1352 Input yin("---\n" 1353 "- -128\n" 1354 "- 0\n" 1355 "- 127\n" 1356 "- -129\n" 1357 "...\n", 1358 /*Ctxt=*/nullptr, 1359 suppressErrorMessages); 1360 yin >> seq; 1361 1362 EXPECT_TRUE(!!yin.error()); 1363 } 1364 1365 1366 // 1367 // Test error handling reading built-in int16_t type 1368 // 1369 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t) 1370 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { 1371 std::vector<int16_t> seq; 1372 Input yin("---\n" 1373 "- 32767\n" 1374 "- 0\n" 1375 "- -32768\n" 1376 "- -32769\n" 1377 "...\n", 1378 /*Ctxt=*/nullptr, 1379 suppressErrorMessages); 1380 yin >> seq; 1381 1382 EXPECT_TRUE(!!yin.error()); 1383 } 1384 1385 1386 // 1387 // Test error handling reading built-in int16_t type 1388 // 1389 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { 1390 std::vector<int16_t> seq; 1391 Input yin("---\n" 1392 "- 32767\n" 1393 "- 0\n" 1394 "- -32768\n" 1395 "- 32768\n" 1396 "...\n", 1397 /*Ctxt=*/nullptr, 1398 suppressErrorMessages); 1399 yin >> seq; 1400 1401 EXPECT_TRUE(!!yin.error()); 1402 } 1403 1404 1405 // 1406 // Test error handling reading built-in int32_t type 1407 // 1408 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t) 1409 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { 1410 std::vector<int32_t> seq; 1411 Input yin("---\n" 1412 "- 2147483647\n" 1413 "- 0\n" 1414 "- -2147483648\n" 1415 "- -2147483649\n" 1416 "...\n", 1417 /*Ctxt=*/nullptr, 1418 suppressErrorMessages); 1419 yin >> seq; 1420 1421 EXPECT_TRUE(!!yin.error()); 1422 } 1423 1424 // 1425 // Test error handling reading built-in int32_t type 1426 // 1427 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { 1428 std::vector<int32_t> seq; 1429 Input yin("---\n" 1430 "- 2147483647\n" 1431 "- 0\n" 1432 "- -2147483648\n" 1433 "- 2147483649\n" 1434 "...\n", 1435 /*Ctxt=*/nullptr, 1436 suppressErrorMessages); 1437 yin >> seq; 1438 1439 EXPECT_TRUE(!!yin.error()); 1440 } 1441 1442 1443 // 1444 // Test error handling reading built-in int64_t type 1445 // 1446 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t) 1447 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { 1448 std::vector<int64_t> seq; 1449 Input yin("---\n" 1450 "- -9223372036854775808\n" 1451 "- 0\n" 1452 "- 9223372036854775807\n" 1453 "- -9223372036854775809\n" 1454 "...\n", 1455 /*Ctxt=*/nullptr, 1456 suppressErrorMessages); 1457 yin >> seq; 1458 1459 EXPECT_TRUE(!!yin.error()); 1460 } 1461 1462 // 1463 // Test error handling reading built-in int64_t type 1464 // 1465 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { 1466 std::vector<int64_t> seq; 1467 Input yin("---\n" 1468 "- -9223372036854775808\n" 1469 "- 0\n" 1470 "- 9223372036854775807\n" 1471 "- 9223372036854775809\n" 1472 "...\n", 1473 /*Ctxt=*/nullptr, 1474 suppressErrorMessages); 1475 yin >> seq; 1476 1477 EXPECT_TRUE(!!yin.error()); 1478 } 1479 1480 // 1481 // Test error handling reading built-in float type 1482 // 1483 LLVM_YAML_IS_SEQUENCE_VECTOR(float) 1484 TEST(YAMLIO, TestReadBuiltInTypesFloatError) { 1485 std::vector<float> seq; 1486 Input yin("---\n" 1487 "- 0.0\n" 1488 "- 1000.1\n" 1489 "- -123.456\n" 1490 "- 1.2.3\n" 1491 "...\n", 1492 /*Ctxt=*/nullptr, 1493 suppressErrorMessages); 1494 yin >> seq; 1495 1496 EXPECT_TRUE(!!yin.error()); 1497 } 1498 1499 // 1500 // Test error handling reading built-in float type 1501 // 1502 LLVM_YAML_IS_SEQUENCE_VECTOR(double) 1503 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { 1504 std::vector<double> seq; 1505 Input yin("---\n" 1506 "- 0.0\n" 1507 "- 1000.1\n" 1508 "- -123.456\n" 1509 "- 1.2.3\n" 1510 "...\n", 1511 /*Ctxt=*/nullptr, 1512 suppressErrorMessages); 1513 yin >> seq; 1514 1515 EXPECT_TRUE(!!yin.error()); 1516 } 1517 1518 // 1519 // Test error handling reading built-in Hex8 type 1520 // 1521 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8) 1522 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { 1523 std::vector<Hex8> seq; 1524 Input yin("---\n" 1525 "- 0x12\n" 1526 "- 0xFE\n" 1527 "- 0x123\n" 1528 "...\n", 1529 /*Ctxt=*/nullptr, 1530 suppressErrorMessages); 1531 yin >> seq; 1532 1533 EXPECT_TRUE(!!yin.error()); 1534 } 1535 1536 1537 // 1538 // Test error handling reading built-in Hex16 type 1539 // 1540 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16) 1541 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { 1542 std::vector<Hex16> seq; 1543 Input yin("---\n" 1544 "- 0x0012\n" 1545 "- 0xFEFF\n" 1546 "- 0x12345\n" 1547 "...\n", 1548 /*Ctxt=*/nullptr, 1549 suppressErrorMessages); 1550 yin >> seq; 1551 1552 EXPECT_TRUE(!!yin.error()); 1553 } 1554 1555 // 1556 // Test error handling reading built-in Hex32 type 1557 // 1558 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32) 1559 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { 1560 std::vector<Hex32> seq; 1561 Input yin("---\n" 1562 "- 0x0012\n" 1563 "- 0xFEFF0000\n" 1564 "- 0x1234556789\n" 1565 "...\n", 1566 /*Ctxt=*/nullptr, 1567 suppressErrorMessages); 1568 yin >> seq; 1569 1570 EXPECT_TRUE(!!yin.error()); 1571 } 1572 1573 // 1574 // Test error handling reading built-in Hex64 type 1575 // 1576 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64) 1577 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { 1578 std::vector<Hex64> seq; 1579 Input yin("---\n" 1580 "- 0x0012\n" 1581 "- 0xFFEEDDCCBBAA9988\n" 1582 "- 0x12345567890ABCDEF0\n" 1583 "...\n", 1584 /*Ctxt=*/nullptr, 1585 suppressErrorMessages); 1586 yin >> seq; 1587 1588 EXPECT_TRUE(!!yin.error()); 1589 } 1590 1591 TEST(YAMLIO, TestMalformedMapFailsGracefully) { 1592 FooBar doc; 1593 { 1594 // We pass the suppressErrorMessages handler to handle the error 1595 // message generated in the constructor of Input. 1596 Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages); 1597 yin >> doc; 1598 EXPECT_TRUE(!!yin.error()); 1599 } 1600 1601 { 1602 Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages); 1603 yin >> doc; 1604 EXPECT_TRUE(!!yin.error()); 1605 } 1606 } 1607 1608 struct OptionalTest { 1609 std::vector<int> Numbers; 1610 }; 1611 1612 struct OptionalTestSeq { 1613 std::vector<OptionalTest> Tests; 1614 }; 1615 1616 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest) 1617 namespace llvm { 1618 namespace yaml { 1619 template <> 1620 struct MappingTraits<OptionalTest> { 1621 static void mapping(IO& IO, OptionalTest &OT) { 1622 IO.mapOptional("Numbers", OT.Numbers); 1623 } 1624 }; 1625 1626 template <> 1627 struct MappingTraits<OptionalTestSeq> { 1628 static void mapping(IO &IO, OptionalTestSeq &OTS) { 1629 IO.mapOptional("Tests", OTS.Tests); 1630 } 1631 }; 1632 } 1633 } 1634 1635 TEST(YAMLIO, SequenceElideTest) { 1636 // Test that writing out a purely optional structure with its fields set to 1637 // default followed by other data is properly read back in. 1638 OptionalTestSeq Seq; 1639 OptionalTest One, Two, Three, Four; 1640 int N[] = {1, 2, 3}; 1641 Three.Numbers.assign(N, N + 3); 1642 Seq.Tests.push_back(One); 1643 Seq.Tests.push_back(Two); 1644 Seq.Tests.push_back(Three); 1645 Seq.Tests.push_back(Four); 1646 1647 std::string intermediate; 1648 { 1649 llvm::raw_string_ostream ostr(intermediate); 1650 Output yout(ostr); 1651 yout << Seq; 1652 } 1653 1654 Input yin(intermediate); 1655 OptionalTestSeq Seq2; 1656 yin >> Seq2; 1657 1658 EXPECT_FALSE(yin.error()); 1659 1660 EXPECT_EQ(4UL, Seq2.Tests.size()); 1661 1662 EXPECT_TRUE(Seq2.Tests[0].Numbers.empty()); 1663 EXPECT_TRUE(Seq2.Tests[1].Numbers.empty()); 1664 1665 EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]); 1666 EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]); 1667 EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]); 1668 1669 EXPECT_TRUE(Seq2.Tests[3].Numbers.empty()); 1670 } 1671 1672 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) { 1673 FooBar doc; 1674 Input yin(""); 1675 yin >> doc; 1676 EXPECT_TRUE(!!yin.error()); 1677 } 1678 1679 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { 1680 OptionalTest doc; 1681 Input yin(""); 1682 yin >> doc; 1683 EXPECT_FALSE(yin.error()); 1684 } 1685 1686 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) { 1687 std::vector<uint8_t> seq; 1688 Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages); 1689 yin >> seq; 1690 1691 EXPECT_FALSE(yin.error()); 1692 EXPECT_TRUE(seq.empty()); 1693 } 1694