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