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/Twine.h" 11 #include "llvm/Support/Casting.h" 12 #include "llvm/Support/Endian.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 struct FooBarContainer { 50 FooBarSequence fbs; 51 }; 52 53 namespace llvm { 54 namespace 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 // 75 TEST(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 96 TEST(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 // 106 TEST(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 // 124 TEST(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 // 178 TEST(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 // 202 TEST(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 241 struct 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 261 namespace llvm { 262 namespace 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 // 292 TEST(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 // 339 TEST(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 392 //===----------------------------------------------------------------------===// 393 // Test endian-aware types 394 //===----------------------------------------------------------------------===// 395 396 struct EndianTypes { 397 typedef llvm::support::detail::packed_endian_specific_integral< 398 float, llvm::support::little, llvm::support::unaligned> 399 ulittle_float; 400 typedef llvm::support::detail::packed_endian_specific_integral< 401 double, llvm::support::little, llvm::support::unaligned> 402 ulittle_double; 403 404 llvm::support::ulittle64_t u64; 405 llvm::support::ulittle32_t u32; 406 llvm::support::ulittle16_t u16; 407 llvm::support::little64_t s64; 408 llvm::support::little32_t s32; 409 llvm::support::little16_t s16; 410 ulittle_float f; 411 ulittle_double d; 412 }; 413 414 namespace llvm { 415 namespace yaml { 416 template <> struct MappingTraits<EndianTypes> { 417 static void mapping(IO &io, EndianTypes &et) { 418 io.mapRequired("u64", et.u64); 419 io.mapRequired("u32", et.u32); 420 io.mapRequired("u16", et.u16); 421 io.mapRequired("s64", et.s64); 422 io.mapRequired("s32", et.s32); 423 io.mapRequired("s16", et.s16); 424 io.mapRequired("f", et.f); 425 io.mapRequired("d", et.d); 426 } 427 }; 428 } 429 } 430 431 // 432 // Test the reading of all endian scalar conversions 433 // 434 TEST(YAMLIO, TestReadEndianTypes) { 435 EndianTypes map; 436 Input yin("---\n" 437 "u64: 5000000000\n" 438 "u32: 4000000000\n" 439 "u16: 65000\n" 440 "s64: -5000000000\n" 441 "s32: -2000000000\n" 442 "s16: -32000\n" 443 "f: 3.25\n" 444 "d: -2.8625\n" 445 "...\n"); 446 yin >> map; 447 448 EXPECT_FALSE(yin.error()); 449 EXPECT_EQ(map.u64, 5000000000ULL); 450 EXPECT_EQ(map.u32, 4000000000U); 451 EXPECT_EQ(map.u16, 65000); 452 EXPECT_EQ(map.s64, -5000000000LL); 453 EXPECT_EQ(map.s32, -2000000000L); 454 EXPECT_EQ(map.s16, -32000); 455 EXPECT_EQ(map.f, 3.25f); 456 EXPECT_EQ(map.d, -2.8625); 457 } 458 459 // 460 // Test writing then reading back all endian-aware scalar types 461 // 462 TEST(YAMLIO, TestReadWriteEndianTypes) { 463 std::string intermediate; 464 { 465 EndianTypes map; 466 map.u64 = 6000000000ULL; 467 map.u32 = 3000000000U; 468 map.u16 = 50000; 469 map.s64 = -6000000000LL; 470 map.s32 = -2000000000; 471 map.s16 = -32000; 472 map.f = 3.25f; 473 map.d = -2.8625; 474 475 llvm::raw_string_ostream ostr(intermediate); 476 Output yout(ostr); 477 yout << map; 478 } 479 480 { 481 Input yin(intermediate); 482 EndianTypes map; 483 yin >> map; 484 485 EXPECT_FALSE(yin.error()); 486 EXPECT_EQ(map.u64, 6000000000ULL); 487 EXPECT_EQ(map.u32, 3000000000U); 488 EXPECT_EQ(map.u16, 50000); 489 EXPECT_EQ(map.s64, -6000000000LL); 490 EXPECT_EQ(map.s32, -2000000000L); 491 EXPECT_EQ(map.s16, -32000); 492 EXPECT_EQ(map.f, 3.25f); 493 EXPECT_EQ(map.d, -2.8625); 494 } 495 } 496 497 struct StringTypes { 498 llvm::StringRef str1; 499 llvm::StringRef str2; 500 llvm::StringRef str3; 501 llvm::StringRef str4; 502 llvm::StringRef str5; 503 llvm::StringRef str6; 504 llvm::StringRef str7; 505 llvm::StringRef str8; 506 llvm::StringRef str9; 507 llvm::StringRef str10; 508 llvm::StringRef str11; 509 std::string stdstr1; 510 std::string stdstr2; 511 std::string stdstr3; 512 std::string stdstr4; 513 std::string stdstr5; 514 std::string stdstr6; 515 std::string stdstr7; 516 std::string stdstr8; 517 std::string stdstr9; 518 std::string stdstr10; 519 std::string stdstr11; 520 }; 521 522 namespace llvm { 523 namespace yaml { 524 template <> 525 struct MappingTraits<StringTypes> { 526 static void mapping(IO &io, StringTypes& st) { 527 io.mapRequired("str1", st.str1); 528 io.mapRequired("str2", st.str2); 529 io.mapRequired("str3", st.str3); 530 io.mapRequired("str4", st.str4); 531 io.mapRequired("str5", st.str5); 532 io.mapRequired("str6", st.str6); 533 io.mapRequired("str7", st.str7); 534 io.mapRequired("str8", st.str8); 535 io.mapRequired("str9", st.str9); 536 io.mapRequired("str10", st.str10); 537 io.mapRequired("str11", st.str11); 538 io.mapRequired("stdstr1", st.stdstr1); 539 io.mapRequired("stdstr2", st.stdstr2); 540 io.mapRequired("stdstr3", st.stdstr3); 541 io.mapRequired("stdstr4", st.stdstr4); 542 io.mapRequired("stdstr5", st.stdstr5); 543 io.mapRequired("stdstr6", st.stdstr6); 544 io.mapRequired("stdstr7", st.stdstr7); 545 io.mapRequired("stdstr8", st.stdstr8); 546 io.mapRequired("stdstr9", st.stdstr9); 547 io.mapRequired("stdstr10", st.stdstr10); 548 io.mapRequired("stdstr11", st.stdstr11); 549 } 550 }; 551 } 552 } 553 554 TEST(YAMLIO, TestReadWriteStringTypes) { 555 std::string intermediate; 556 { 557 StringTypes map; 558 map.str1 = "'aaa"; 559 map.str2 = "\"bbb"; 560 map.str3 = "`ccc"; 561 map.str4 = "@ddd"; 562 map.str5 = ""; 563 map.str6 = "0000000004000000"; 564 map.str7 = "true"; 565 map.str8 = "FALSE"; 566 map.str9 = "~"; 567 map.str10 = "0.2e20"; 568 map.str11 = "0x30"; 569 map.stdstr1 = "'eee"; 570 map.stdstr2 = "\"fff"; 571 map.stdstr3 = "`ggg"; 572 map.stdstr4 = "@hhh"; 573 map.stdstr5 = ""; 574 map.stdstr6 = "0000000004000000"; 575 map.stdstr7 = "true"; 576 map.stdstr8 = "FALSE"; 577 map.stdstr9 = "~"; 578 map.stdstr10 = "0.2e20"; 579 map.stdstr11 = "0x30"; 580 581 llvm::raw_string_ostream ostr(intermediate); 582 Output yout(ostr); 583 yout << map; 584 } 585 586 llvm::StringRef flowOut(intermediate); 587 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa")); 588 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'")); 589 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); 590 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); 591 EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); 592 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n")); 593 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n")); 594 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n")); 595 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n")); 596 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n")); 597 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n")); 598 EXPECT_NE(std::string::npos, flowOut.find("'''eee")); 599 EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); 600 EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); 601 EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); 602 EXPECT_NE(std::string::npos, flowOut.find("''\n")); 603 EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n")); 604 605 { 606 Input yin(intermediate); 607 StringTypes map; 608 yin >> map; 609 610 EXPECT_FALSE(yin.error()); 611 EXPECT_TRUE(map.str1.equals("'aaa")); 612 EXPECT_TRUE(map.str2.equals("\"bbb")); 613 EXPECT_TRUE(map.str3.equals("`ccc")); 614 EXPECT_TRUE(map.str4.equals("@ddd")); 615 EXPECT_TRUE(map.str5.equals("")); 616 EXPECT_TRUE(map.str6.equals("0000000004000000")); 617 EXPECT_TRUE(map.stdstr1 == "'eee"); 618 EXPECT_TRUE(map.stdstr2 == "\"fff"); 619 EXPECT_TRUE(map.stdstr3 == "`ggg"); 620 EXPECT_TRUE(map.stdstr4 == "@hhh"); 621 EXPECT_TRUE(map.stdstr5 == ""); 622 EXPECT_TRUE(map.stdstr6 == "0000000004000000"); 623 } 624 } 625 626 //===----------------------------------------------------------------------===// 627 // Test ScalarEnumerationTraits 628 //===----------------------------------------------------------------------===// 629 630 enum Colors { 631 cRed, 632 cBlue, 633 cGreen, 634 cYellow 635 }; 636 637 struct ColorMap { 638 Colors c1; 639 Colors c2; 640 Colors c3; 641 Colors c4; 642 Colors c5; 643 Colors c6; 644 }; 645 646 namespace llvm { 647 namespace yaml { 648 template <> 649 struct ScalarEnumerationTraits<Colors> { 650 static void enumeration(IO &io, Colors &value) { 651 io.enumCase(value, "red", cRed); 652 io.enumCase(value, "blue", cBlue); 653 io.enumCase(value, "green", cGreen); 654 io.enumCase(value, "yellow",cYellow); 655 } 656 }; 657 template <> 658 struct MappingTraits<ColorMap> { 659 static void mapping(IO &io, ColorMap& c) { 660 io.mapRequired("c1", c.c1); 661 io.mapRequired("c2", c.c2); 662 io.mapRequired("c3", c.c3); 663 io.mapOptional("c4", c.c4, cBlue); // supplies default 664 io.mapOptional("c5", c.c5, cYellow); // supplies default 665 io.mapOptional("c6", c.c6, cRed); // supplies default 666 } 667 }; 668 } 669 } 670 671 672 // 673 // Test reading enumerated scalars 674 // 675 TEST(YAMLIO, TestEnumRead) { 676 ColorMap map; 677 Input yin("---\n" 678 "c1: blue\n" 679 "c2: red\n" 680 "c3: green\n" 681 "c5: yellow\n" 682 "...\n"); 683 yin >> map; 684 685 EXPECT_FALSE(yin.error()); 686 EXPECT_EQ(cBlue, map.c1); 687 EXPECT_EQ(cRed, map.c2); 688 EXPECT_EQ(cGreen, map.c3); 689 EXPECT_EQ(cBlue, map.c4); // tests default 690 EXPECT_EQ(cYellow,map.c5); // tests overridden 691 EXPECT_EQ(cRed, map.c6); // tests default 692 } 693 694 695 696 //===----------------------------------------------------------------------===// 697 // Test ScalarBitSetTraits 698 //===----------------------------------------------------------------------===// 699 700 enum MyFlags { 701 flagNone = 0, 702 flagBig = 1 << 0, 703 flagFlat = 1 << 1, 704 flagRound = 1 << 2, 705 flagPointy = 1 << 3 706 }; 707 inline MyFlags operator|(MyFlags a, MyFlags b) { 708 return static_cast<MyFlags>( 709 static_cast<uint32_t>(a) | static_cast<uint32_t>(b)); 710 } 711 712 struct FlagsMap { 713 MyFlags f1; 714 MyFlags f2; 715 MyFlags f3; 716 MyFlags f4; 717 }; 718 719 720 namespace llvm { 721 namespace yaml { 722 template <> 723 struct ScalarBitSetTraits<MyFlags> { 724 static void bitset(IO &io, MyFlags &value) { 725 io.bitSetCase(value, "big", flagBig); 726 io.bitSetCase(value, "flat", flagFlat); 727 io.bitSetCase(value, "round", flagRound); 728 io.bitSetCase(value, "pointy",flagPointy); 729 } 730 }; 731 template <> 732 struct MappingTraits<FlagsMap> { 733 static void mapping(IO &io, FlagsMap& c) { 734 io.mapRequired("f1", c.f1); 735 io.mapRequired("f2", c.f2); 736 io.mapRequired("f3", c.f3); 737 io.mapOptional("f4", c.f4, MyFlags(flagRound)); 738 } 739 }; 740 } 741 } 742 743 744 // 745 // Test reading flow sequence representing bit-mask values 746 // 747 TEST(YAMLIO, TestFlagsRead) { 748 FlagsMap map; 749 Input yin("---\n" 750 "f1: [ big ]\n" 751 "f2: [ round, flat ]\n" 752 "f3: []\n" 753 "...\n"); 754 yin >> map; 755 756 EXPECT_FALSE(yin.error()); 757 EXPECT_EQ(flagBig, map.f1); 758 EXPECT_EQ(flagRound|flagFlat, map.f2); 759 EXPECT_EQ(flagNone, map.f3); // check empty set 760 EXPECT_EQ(flagRound, map.f4); // check optional key 761 } 762 763 764 // 765 // Test writing then reading back bit-mask values 766 // 767 TEST(YAMLIO, TestReadWriteFlags) { 768 std::string intermediate; 769 { 770 FlagsMap map; 771 map.f1 = flagBig; 772 map.f2 = flagRound | flagFlat; 773 map.f3 = flagNone; 774 map.f4 = flagNone; 775 776 llvm::raw_string_ostream ostr(intermediate); 777 Output yout(ostr); 778 yout << map; 779 } 780 781 { 782 Input yin(intermediate); 783 FlagsMap map2; 784 yin >> map2; 785 786 EXPECT_FALSE(yin.error()); 787 EXPECT_EQ(flagBig, map2.f1); 788 EXPECT_EQ(flagRound|flagFlat, map2.f2); 789 EXPECT_EQ(flagNone, map2.f3); 790 //EXPECT_EQ(flagRound, map2.f4); // check optional key 791 } 792 } 793 794 795 796 //===----------------------------------------------------------------------===// 797 // Test ScalarTraits 798 //===----------------------------------------------------------------------===// 799 800 struct MyCustomType { 801 int length; 802 int width; 803 }; 804 805 struct MyCustomTypeMap { 806 MyCustomType f1; 807 MyCustomType f2; 808 int f3; 809 }; 810 811 812 namespace llvm { 813 namespace yaml { 814 template <> 815 struct MappingTraits<MyCustomTypeMap> { 816 static void mapping(IO &io, MyCustomTypeMap& s) { 817 io.mapRequired("f1", s.f1); 818 io.mapRequired("f2", s.f2); 819 io.mapRequired("f3", s.f3); 820 } 821 }; 822 // MyCustomType is formatted as a yaml scalar. A value of 823 // {length=3, width=4} would be represented in yaml as "3 by 4". 824 template<> 825 struct ScalarTraits<MyCustomType> { 826 static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) { 827 out << llvm::format("%d by %d", value.length, value.width); 828 } 829 static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) { 830 size_t byStart = scalar.find("by"); 831 if ( byStart != StringRef::npos ) { 832 StringRef lenStr = scalar.slice(0, byStart); 833 lenStr = lenStr.rtrim(); 834 if ( lenStr.getAsInteger(0, value.length) ) { 835 return "malformed length"; 836 } 837 StringRef widthStr = scalar.drop_front(byStart+2); 838 widthStr = widthStr.ltrim(); 839 if ( widthStr.getAsInteger(0, value.width) ) { 840 return "malformed width"; 841 } 842 return StringRef(); 843 } 844 else { 845 return "malformed by"; 846 } 847 } 848 static bool mustQuote(StringRef) { return true; } 849 }; 850 } 851 } 852 853 854 // 855 // Test writing then reading back custom values 856 // 857 TEST(YAMLIO, TestReadWriteMyCustomType) { 858 std::string intermediate; 859 { 860 MyCustomTypeMap map; 861 map.f1.length = 1; 862 map.f1.width = 4; 863 map.f2.length = 100; 864 map.f2.width = 400; 865 map.f3 = 10; 866 867 llvm::raw_string_ostream ostr(intermediate); 868 Output yout(ostr); 869 yout << map; 870 } 871 872 { 873 Input yin(intermediate); 874 MyCustomTypeMap map2; 875 yin >> map2; 876 877 EXPECT_FALSE(yin.error()); 878 EXPECT_EQ(1, map2.f1.length); 879 EXPECT_EQ(4, map2.f1.width); 880 EXPECT_EQ(100, map2.f2.length); 881 EXPECT_EQ(400, map2.f2.width); 882 EXPECT_EQ(10, map2.f3); 883 } 884 } 885 886 887 //===----------------------------------------------------------------------===// 888 // Test BlockScalarTraits 889 //===----------------------------------------------------------------------===// 890 891 struct MultilineStringType { 892 std::string str; 893 }; 894 895 struct MultilineStringTypeMap { 896 MultilineStringType name; 897 MultilineStringType description; 898 MultilineStringType ingredients; 899 MultilineStringType recipes; 900 MultilineStringType warningLabels; 901 MultilineStringType documentation; 902 int price; 903 }; 904 905 namespace llvm { 906 namespace yaml { 907 template <> 908 struct MappingTraits<MultilineStringTypeMap> { 909 static void mapping(IO &io, MultilineStringTypeMap& s) { 910 io.mapRequired("name", s.name); 911 io.mapRequired("description", s.description); 912 io.mapRequired("ingredients", s.ingredients); 913 io.mapRequired("recipes", s.recipes); 914 io.mapRequired("warningLabels", s.warningLabels); 915 io.mapRequired("documentation", s.documentation); 916 io.mapRequired("price", s.price); 917 } 918 }; 919 920 // MultilineStringType is formatted as a yaml block literal scalar. A value of 921 // "Hello\nWorld" would be represented in yaml as 922 // | 923 // Hello 924 // World 925 template <> 926 struct BlockScalarTraits<MultilineStringType> { 927 static void output(const MultilineStringType &value, void *ctxt, 928 llvm::raw_ostream &out) { 929 out << value.str; 930 } 931 static StringRef input(StringRef scalar, void *ctxt, 932 MultilineStringType &value) { 933 value.str = scalar.str(); 934 return StringRef(); 935 } 936 }; 937 } 938 } 939 940 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType) 941 942 // 943 // Test writing then reading back custom values 944 // 945 TEST(YAMLIO, TestReadWriteMultilineStringType) { 946 std::string intermediate; 947 { 948 MultilineStringTypeMap map; 949 map.name.str = "An Item"; 950 map.description.str = "Hello\nWorld"; 951 map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n"; 952 map.recipes.str = "\n\nTest 1\n\n\n"; 953 map.warningLabels.str = ""; 954 map.documentation.str = "\n\n"; 955 map.price = 350; 956 957 llvm::raw_string_ostream ostr(intermediate); 958 Output yout(ostr); 959 yout << map; 960 } 961 { 962 Input yin(intermediate); 963 MultilineStringTypeMap map2; 964 yin >> map2; 965 966 EXPECT_FALSE(yin.error()); 967 EXPECT_EQ(map2.name.str, "An Item\n"); 968 EXPECT_EQ(map2.description.str, "Hello\nWorld\n"); 969 EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n"); 970 EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n"); 971 EXPECT_TRUE(map2.warningLabels.str.empty()); 972 EXPECT_TRUE(map2.documentation.str.empty()); 973 EXPECT_EQ(map2.price, 350); 974 } 975 } 976 977 // 978 // Test writing then reading back custom values 979 // 980 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) { 981 std::string intermediate; 982 { 983 std::vector<MultilineStringType> documents; 984 MultilineStringType doc; 985 doc.str = "Hello\nWorld"; 986 documents.push_back(doc); 987 988 llvm::raw_string_ostream ostr(intermediate); 989 Output yout(ostr); 990 yout << documents; 991 992 // Verify that the block scalar header was written out on the same line 993 // as the document marker. 994 EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |")); 995 } 996 { 997 Input yin(intermediate); 998 std::vector<MultilineStringType> documents2; 999 yin >> documents2; 1000 1001 EXPECT_FALSE(yin.error()); 1002 EXPECT_EQ(documents2.size(), size_t(1)); 1003 EXPECT_EQ(documents2[0].str, "Hello\nWorld\n"); 1004 } 1005 } 1006 1007 TEST(YAMLIO, TestReadWriteBlockScalarValue) { 1008 std::string intermediate; 1009 { 1010 MultilineStringType doc; 1011 doc.str = "Just a block\nscalar doc"; 1012 1013 llvm::raw_string_ostream ostr(intermediate); 1014 Output yout(ostr); 1015 yout << doc; 1016 } 1017 { 1018 Input yin(intermediate); 1019 MultilineStringType doc; 1020 yin >> doc; 1021 1022 EXPECT_FALSE(yin.error()); 1023 EXPECT_EQ(doc.str, "Just a block\nscalar doc\n"); 1024 } 1025 } 1026 1027 //===----------------------------------------------------------------------===// 1028 // Test flow sequences 1029 //===----------------------------------------------------------------------===// 1030 1031 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber) 1032 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber) 1033 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef) 1034 1035 namespace llvm { 1036 namespace yaml { 1037 template<> 1038 struct ScalarTraits<MyNumber> { 1039 static void output(const MyNumber &value, void *, llvm::raw_ostream &out) { 1040 out << value; 1041 } 1042 1043 static StringRef input(StringRef scalar, void *, MyNumber &value) { 1044 long long n; 1045 if ( getAsSignedInteger(scalar, 0, n) ) 1046 return "invalid number"; 1047 value = n; 1048 return StringRef(); 1049 } 1050 1051 static bool mustQuote(StringRef) { return false; } 1052 }; 1053 } 1054 } 1055 1056 struct NameAndNumbers { 1057 llvm::StringRef name; 1058 std::vector<llvm::StringRef> strings; 1059 std::vector<MyNumber> single; 1060 std::vector<MyNumber> numbers; 1061 }; 1062 1063 namespace llvm { 1064 namespace yaml { 1065 template <> 1066 struct MappingTraits<NameAndNumbers> { 1067 static void mapping(IO &io, NameAndNumbers& nn) { 1068 io.mapRequired("name", nn.name); 1069 io.mapRequired("strings", nn.strings); 1070 io.mapRequired("single", nn.single); 1071 io.mapRequired("numbers", nn.numbers); 1072 } 1073 }; 1074 } 1075 } 1076 1077 typedef std::vector<MyNumber> MyNumberFlowSequence; 1078 1079 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence) 1080 1081 struct NameAndNumbersFlow { 1082 llvm::StringRef name; 1083 std::vector<MyNumberFlowSequence> sequenceOfNumbers; 1084 }; 1085 1086 namespace llvm { 1087 namespace yaml { 1088 template <> 1089 struct MappingTraits<NameAndNumbersFlow> { 1090 static void mapping(IO &io, NameAndNumbersFlow& nn) { 1091 io.mapRequired("name", nn.name); 1092 io.mapRequired("sequenceOfNumbers", nn.sequenceOfNumbers); 1093 } 1094 }; 1095 } 1096 } 1097 1098 // 1099 // Test writing then reading back custom values 1100 // 1101 TEST(YAMLIO, TestReadWriteMyFlowSequence) { 1102 std::string intermediate; 1103 { 1104 NameAndNumbers map; 1105 map.name = "hello"; 1106 map.strings.push_back(llvm::StringRef("one")); 1107 map.strings.push_back(llvm::StringRef("two")); 1108 map.single.push_back(1); 1109 map.numbers.push_back(10); 1110 map.numbers.push_back(-30); 1111 map.numbers.push_back(1024); 1112 1113 llvm::raw_string_ostream ostr(intermediate); 1114 Output yout(ostr); 1115 yout << map; 1116 1117 // Verify sequences were written in flow style 1118 ostr.flush(); 1119 llvm::StringRef flowOut(intermediate); 1120 EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two")); 1121 EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024")); 1122 } 1123 1124 { 1125 Input yin(intermediate); 1126 NameAndNumbers map2; 1127 yin >> map2; 1128 1129 EXPECT_FALSE(yin.error()); 1130 EXPECT_TRUE(map2.name.equals("hello")); 1131 EXPECT_EQ(map2.strings.size(), 2UL); 1132 EXPECT_TRUE(map2.strings[0].equals("one")); 1133 EXPECT_TRUE(map2.strings[1].equals("two")); 1134 EXPECT_EQ(map2.single.size(), 1UL); 1135 EXPECT_EQ(1, map2.single[0]); 1136 EXPECT_EQ(map2.numbers.size(), 3UL); 1137 EXPECT_EQ(10, map2.numbers[0]); 1138 EXPECT_EQ(-30, map2.numbers[1]); 1139 EXPECT_EQ(1024, map2.numbers[2]); 1140 } 1141 } 1142 1143 1144 // 1145 // Test writing then reading back a sequence of flow sequences. 1146 // 1147 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) { 1148 std::string intermediate; 1149 { 1150 NameAndNumbersFlow map; 1151 map.name = "hello"; 1152 MyNumberFlowSequence single = { 0 }; 1153 MyNumberFlowSequence numbers = { 12, 1, -512 }; 1154 map.sequenceOfNumbers.push_back(single); 1155 map.sequenceOfNumbers.push_back(numbers); 1156 map.sequenceOfNumbers.push_back(MyNumberFlowSequence()); 1157 1158 llvm::raw_string_ostream ostr(intermediate); 1159 Output yout(ostr); 1160 yout << map; 1161 1162 // Verify sequences were written in flow style 1163 // and that the parent sequence used '-'. 1164 ostr.flush(); 1165 llvm::StringRef flowOut(intermediate); 1166 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]")); 1167 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]")); 1168 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ ]")); 1169 } 1170 1171 { 1172 Input yin(intermediate); 1173 NameAndNumbersFlow map2; 1174 yin >> map2; 1175 1176 EXPECT_FALSE(yin.error()); 1177 EXPECT_TRUE(map2.name.equals("hello")); 1178 EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL); 1179 EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL); 1180 EXPECT_EQ(0, map2.sequenceOfNumbers[0][0]); 1181 EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL); 1182 EXPECT_EQ(12, map2.sequenceOfNumbers[1][0]); 1183 EXPECT_EQ(1, map2.sequenceOfNumbers[1][1]); 1184 EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]); 1185 EXPECT_TRUE(map2.sequenceOfNumbers[2].empty()); 1186 } 1187 } 1188 1189 //===----------------------------------------------------------------------===// 1190 // Test normalizing/denormalizing 1191 //===----------------------------------------------------------------------===// 1192 1193 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds) 1194 1195 typedef std::vector<TotalSeconds> SecondsSequence; 1196 1197 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds) 1198 1199 1200 namespace llvm { 1201 namespace yaml { 1202 template <> 1203 struct MappingTraits<TotalSeconds> { 1204 1205 class NormalizedSeconds { 1206 public: 1207 NormalizedSeconds(IO &io) 1208 : hours(0), minutes(0), seconds(0) { 1209 } 1210 NormalizedSeconds(IO &, TotalSeconds &secs) 1211 : hours(secs/3600), 1212 minutes((secs - (hours*3600))/60), 1213 seconds(secs % 60) { 1214 } 1215 TotalSeconds denormalize(IO &) { 1216 return TotalSeconds(hours*3600 + minutes*60 + seconds); 1217 } 1218 1219 uint32_t hours; 1220 uint8_t minutes; 1221 uint8_t seconds; 1222 }; 1223 1224 static void mapping(IO &io, TotalSeconds &secs) { 1225 MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs); 1226 1227 io.mapOptional("hours", keys->hours, (uint32_t)0); 1228 io.mapOptional("minutes", keys->minutes, (uint8_t)0); 1229 io.mapRequired("seconds", keys->seconds); 1230 } 1231 }; 1232 } 1233 } 1234 1235 1236 // 1237 // Test the reading of a yaml sequence of mappings 1238 // 1239 TEST(YAMLIO, TestReadMySecondsSequence) { 1240 SecondsSequence seq; 1241 Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n"); 1242 yin >> seq; 1243 1244 EXPECT_FALSE(yin.error()); 1245 EXPECT_EQ(seq.size(), 2UL); 1246 EXPECT_EQ(seq[0], 3605U); 1247 EXPECT_EQ(seq[1], 59U); 1248 } 1249 1250 1251 // 1252 // Test writing then reading back custom values 1253 // 1254 TEST(YAMLIO, TestReadWriteMySecondsSequence) { 1255 std::string intermediate; 1256 { 1257 SecondsSequence seq; 1258 seq.push_back(4000); 1259 seq.push_back(500); 1260 seq.push_back(59); 1261 1262 llvm::raw_string_ostream ostr(intermediate); 1263 Output yout(ostr); 1264 yout << seq; 1265 } 1266 { 1267 Input yin(intermediate); 1268 SecondsSequence seq2; 1269 yin >> seq2; 1270 1271 EXPECT_FALSE(yin.error()); 1272 EXPECT_EQ(seq2.size(), 3UL); 1273 EXPECT_EQ(seq2[0], 4000U); 1274 EXPECT_EQ(seq2[1], 500U); 1275 EXPECT_EQ(seq2[2], 59U); 1276 } 1277 } 1278 1279 1280 //===----------------------------------------------------------------------===// 1281 // Test dynamic typing 1282 //===----------------------------------------------------------------------===// 1283 1284 enum AFlags { 1285 a1, 1286 a2, 1287 a3 1288 }; 1289 1290 enum BFlags { 1291 b1, 1292 b2, 1293 b3 1294 }; 1295 1296 enum Kind { 1297 kindA, 1298 kindB 1299 }; 1300 1301 struct KindAndFlags { 1302 KindAndFlags() : kind(kindA), flags(0) { } 1303 KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { } 1304 Kind kind; 1305 uint32_t flags; 1306 }; 1307 1308 typedef std::vector<KindAndFlags> KindAndFlagsSequence; 1309 1310 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags) 1311 1312 namespace llvm { 1313 namespace yaml { 1314 template <> 1315 struct ScalarEnumerationTraits<AFlags> { 1316 static void enumeration(IO &io, AFlags &value) { 1317 io.enumCase(value, "a1", a1); 1318 io.enumCase(value, "a2", a2); 1319 io.enumCase(value, "a3", a3); 1320 } 1321 }; 1322 template <> 1323 struct ScalarEnumerationTraits<BFlags> { 1324 static void enumeration(IO &io, BFlags &value) { 1325 io.enumCase(value, "b1", b1); 1326 io.enumCase(value, "b2", b2); 1327 io.enumCase(value, "b3", b3); 1328 } 1329 }; 1330 template <> 1331 struct ScalarEnumerationTraits<Kind> { 1332 static void enumeration(IO &io, Kind &value) { 1333 io.enumCase(value, "A", kindA); 1334 io.enumCase(value, "B", kindB); 1335 } 1336 }; 1337 template <> 1338 struct MappingTraits<KindAndFlags> { 1339 static void mapping(IO &io, KindAndFlags& kf) { 1340 io.mapRequired("kind", kf.kind); 1341 // Type of "flags" field varies depending on "kind" field. 1342 // Use memcpy here to avoid breaking strict aliasing rules. 1343 if (kf.kind == kindA) { 1344 AFlags aflags = static_cast<AFlags>(kf.flags); 1345 io.mapRequired("flags", aflags); 1346 kf.flags = aflags; 1347 } else { 1348 BFlags bflags = static_cast<BFlags>(kf.flags); 1349 io.mapRequired("flags", bflags); 1350 kf.flags = bflags; 1351 } 1352 } 1353 }; 1354 } 1355 } 1356 1357 1358 // 1359 // Test the reading of a yaml sequence dynamic types 1360 // 1361 TEST(YAMLIO, TestReadKindAndFlagsSequence) { 1362 KindAndFlagsSequence seq; 1363 Input yin("---\n - kind: A\n flags: a2\n - kind: B\n flags: b1\n...\n"); 1364 yin >> seq; 1365 1366 EXPECT_FALSE(yin.error()); 1367 EXPECT_EQ(seq.size(), 2UL); 1368 EXPECT_EQ(seq[0].kind, kindA); 1369 EXPECT_EQ(seq[0].flags, (uint32_t)a2); 1370 EXPECT_EQ(seq[1].kind, kindB); 1371 EXPECT_EQ(seq[1].flags, (uint32_t)b1); 1372 } 1373 1374 // 1375 // Test writing then reading back dynamic types 1376 // 1377 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) { 1378 std::string intermediate; 1379 { 1380 KindAndFlagsSequence seq; 1381 seq.push_back(KindAndFlags(kindA,a1)); 1382 seq.push_back(KindAndFlags(kindB,b1)); 1383 seq.push_back(KindAndFlags(kindA,a2)); 1384 seq.push_back(KindAndFlags(kindB,b2)); 1385 seq.push_back(KindAndFlags(kindA,a3)); 1386 1387 llvm::raw_string_ostream ostr(intermediate); 1388 Output yout(ostr); 1389 yout << seq; 1390 } 1391 { 1392 Input yin(intermediate); 1393 KindAndFlagsSequence seq2; 1394 yin >> seq2; 1395 1396 EXPECT_FALSE(yin.error()); 1397 EXPECT_EQ(seq2.size(), 5UL); 1398 EXPECT_EQ(seq2[0].kind, kindA); 1399 EXPECT_EQ(seq2[0].flags, (uint32_t)a1); 1400 EXPECT_EQ(seq2[1].kind, kindB); 1401 EXPECT_EQ(seq2[1].flags, (uint32_t)b1); 1402 EXPECT_EQ(seq2[2].kind, kindA); 1403 EXPECT_EQ(seq2[2].flags, (uint32_t)a2); 1404 EXPECT_EQ(seq2[3].kind, kindB); 1405 EXPECT_EQ(seq2[3].flags, (uint32_t)b2); 1406 EXPECT_EQ(seq2[4].kind, kindA); 1407 EXPECT_EQ(seq2[4].flags, (uint32_t)a3); 1408 } 1409 } 1410 1411 1412 //===----------------------------------------------------------------------===// 1413 // Test document list 1414 //===----------------------------------------------------------------------===// 1415 1416 struct FooBarMap { 1417 int foo; 1418 int bar; 1419 }; 1420 typedef std::vector<FooBarMap> FooBarMapDocumentList; 1421 1422 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap) 1423 1424 1425 namespace llvm { 1426 namespace yaml { 1427 template <> 1428 struct MappingTraits<FooBarMap> { 1429 static void mapping(IO &io, FooBarMap& fb) { 1430 io.mapRequired("foo", fb.foo); 1431 io.mapRequired("bar", fb.bar); 1432 } 1433 }; 1434 } 1435 } 1436 1437 1438 // 1439 // Test the reading of a yaml mapping 1440 // 1441 TEST(YAMLIO, TestDocRead) { 1442 FooBarMap doc; 1443 Input yin("---\nfoo: 3\nbar: 5\n...\n"); 1444 yin >> doc; 1445 1446 EXPECT_FALSE(yin.error()); 1447 EXPECT_EQ(doc.foo, 3); 1448 EXPECT_EQ(doc.bar,5); 1449 } 1450 1451 1452 1453 // 1454 // Test writing then reading back a sequence of mappings 1455 // 1456 TEST(YAMLIO, TestSequenceDocListWriteAndRead) { 1457 std::string intermediate; 1458 { 1459 FooBarMap doc1; 1460 doc1.foo = 10; 1461 doc1.bar = -3; 1462 FooBarMap doc2; 1463 doc2.foo = 257; 1464 doc2.bar = 0; 1465 std::vector<FooBarMap> docList; 1466 docList.push_back(doc1); 1467 docList.push_back(doc2); 1468 1469 llvm::raw_string_ostream ostr(intermediate); 1470 Output yout(ostr); 1471 yout << docList; 1472 } 1473 1474 1475 { 1476 Input yin(intermediate); 1477 std::vector<FooBarMap> docList2; 1478 yin >> docList2; 1479 1480 EXPECT_FALSE(yin.error()); 1481 EXPECT_EQ(docList2.size(), 2UL); 1482 FooBarMap& map1 = docList2[0]; 1483 FooBarMap& map2 = docList2[1]; 1484 EXPECT_EQ(map1.foo, 10); 1485 EXPECT_EQ(map1.bar, -3); 1486 EXPECT_EQ(map2.foo, 257); 1487 EXPECT_EQ(map2.bar, 0); 1488 } 1489 } 1490 1491 //===----------------------------------------------------------------------===// 1492 // Test document tags 1493 //===----------------------------------------------------------------------===// 1494 1495 struct MyDouble { 1496 MyDouble() : value(0.0) { } 1497 MyDouble(double x) : value(x) { } 1498 double value; 1499 }; 1500 1501 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble) 1502 1503 1504 namespace llvm { 1505 namespace yaml { 1506 template <> 1507 struct MappingTraits<MyDouble> { 1508 static void mapping(IO &io, MyDouble &d) { 1509 if (io.mapTag("!decimal", true)) { 1510 mappingDecimal(io, d); 1511 } else if (io.mapTag("!fraction")) { 1512 mappingFraction(io, d); 1513 } 1514 } 1515 static void mappingDecimal(IO &io, MyDouble &d) { 1516 io.mapRequired("value", d.value); 1517 } 1518 static void mappingFraction(IO &io, MyDouble &d) { 1519 double num, denom; 1520 io.mapRequired("numerator", num); 1521 io.mapRequired("denominator", denom); 1522 // convert fraction to double 1523 d.value = num/denom; 1524 } 1525 }; 1526 } 1527 } 1528 1529 1530 // 1531 // Test the reading of two different tagged yaml documents. 1532 // 1533 TEST(YAMLIO, TestTaggedDocuments) { 1534 std::vector<MyDouble> docList; 1535 Input yin("--- !decimal\nvalue: 3.0\n" 1536 "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n"); 1537 yin >> docList; 1538 EXPECT_FALSE(yin.error()); 1539 EXPECT_EQ(docList.size(), 2UL); 1540 EXPECT_EQ(docList[0].value, 3.0); 1541 EXPECT_EQ(docList[1].value, 4.5); 1542 } 1543 1544 1545 1546 // 1547 // Test writing then reading back tagged documents 1548 // 1549 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) { 1550 std::string intermediate; 1551 { 1552 MyDouble a(10.25); 1553 MyDouble b(-3.75); 1554 std::vector<MyDouble> docList; 1555 docList.push_back(a); 1556 docList.push_back(b); 1557 1558 llvm::raw_string_ostream ostr(intermediate); 1559 Output yout(ostr); 1560 yout << docList; 1561 } 1562 1563 { 1564 Input yin(intermediate); 1565 std::vector<MyDouble> docList2; 1566 yin >> docList2; 1567 1568 EXPECT_FALSE(yin.error()); 1569 EXPECT_EQ(docList2.size(), 2UL); 1570 EXPECT_EQ(docList2[0].value, 10.25); 1571 EXPECT_EQ(docList2[1].value, -3.75); 1572 } 1573 } 1574 1575 1576 //===----------------------------------------------------------------------===// 1577 // Test mapping validation 1578 //===----------------------------------------------------------------------===// 1579 1580 struct MyValidation { 1581 double value; 1582 }; 1583 1584 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation) 1585 1586 namespace llvm { 1587 namespace yaml { 1588 template <> 1589 struct MappingTraits<MyValidation> { 1590 static void mapping(IO &io, MyValidation &d) { 1591 io.mapRequired("value", d.value); 1592 } 1593 static StringRef validate(IO &io, MyValidation &d) { 1594 if (d.value < 0) 1595 return "negative value"; 1596 return StringRef(); 1597 } 1598 }; 1599 } 1600 } 1601 1602 1603 // 1604 // Test that validate() is called and complains about the negative value. 1605 // 1606 TEST(YAMLIO, TestValidatingInput) { 1607 std::vector<MyValidation> docList; 1608 Input yin("--- \nvalue: 3.0\n" 1609 "--- \nvalue: -1.0\n...\n", 1610 nullptr, suppressErrorMessages); 1611 yin >> docList; 1612 EXPECT_TRUE(!!yin.error()); 1613 } 1614 1615 //===----------------------------------------------------------------------===// 1616 // Test flow mapping 1617 //===----------------------------------------------------------------------===// 1618 1619 struct FlowFooBar { 1620 int foo; 1621 int bar; 1622 1623 FlowFooBar() : foo(0), bar(0) {} 1624 FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {} 1625 }; 1626 1627 typedef std::vector<FlowFooBar> FlowFooBarSequence; 1628 1629 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar) 1630 1631 struct FlowFooBarDoc { 1632 FlowFooBar attribute; 1633 FlowFooBarSequence seq; 1634 }; 1635 1636 namespace llvm { 1637 namespace yaml { 1638 template <> 1639 struct MappingTraits<FlowFooBar> { 1640 static void mapping(IO &io, FlowFooBar &fb) { 1641 io.mapRequired("foo", fb.foo); 1642 io.mapRequired("bar", fb.bar); 1643 } 1644 1645 static const bool flow = true; 1646 }; 1647 1648 template <> 1649 struct MappingTraits<FlowFooBarDoc> { 1650 static void mapping(IO &io, FlowFooBarDoc &fb) { 1651 io.mapRequired("attribute", fb.attribute); 1652 io.mapRequired("seq", fb.seq); 1653 } 1654 }; 1655 } 1656 } 1657 1658 // 1659 // Test writing then reading back custom mappings 1660 // 1661 TEST(YAMLIO, TestReadWriteMyFlowMapping) { 1662 std::string intermediate; 1663 { 1664 FlowFooBarDoc doc; 1665 doc.attribute = FlowFooBar(42, 907); 1666 doc.seq.push_back(FlowFooBar(1, 2)); 1667 doc.seq.push_back(FlowFooBar(0, 0)); 1668 doc.seq.push_back(FlowFooBar(-1, 1024)); 1669 1670 llvm::raw_string_ostream ostr(intermediate); 1671 Output yout(ostr); 1672 yout << doc; 1673 1674 // Verify that mappings were written in flow style 1675 ostr.flush(); 1676 llvm::StringRef flowOut(intermediate); 1677 EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }")); 1678 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }")); 1679 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }")); 1680 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }")); 1681 } 1682 1683 { 1684 Input yin(intermediate); 1685 FlowFooBarDoc doc2; 1686 yin >> doc2; 1687 1688 EXPECT_FALSE(yin.error()); 1689 EXPECT_EQ(doc2.attribute.foo, 42); 1690 EXPECT_EQ(doc2.attribute.bar, 907); 1691 EXPECT_EQ(doc2.seq.size(), 3UL); 1692 EXPECT_EQ(doc2.seq[0].foo, 1); 1693 EXPECT_EQ(doc2.seq[0].bar, 2); 1694 EXPECT_EQ(doc2.seq[1].foo, 0); 1695 EXPECT_EQ(doc2.seq[1].bar, 0); 1696 EXPECT_EQ(doc2.seq[2].foo, -1); 1697 EXPECT_EQ(doc2.seq[2].bar, 1024); 1698 } 1699 } 1700 1701 //===----------------------------------------------------------------------===// 1702 // Test error handling 1703 //===----------------------------------------------------------------------===// 1704 1705 // 1706 // Test error handling of unknown enumerated scalar 1707 // 1708 TEST(YAMLIO, TestColorsReadError) { 1709 ColorMap map; 1710 Input yin("---\n" 1711 "c1: blue\n" 1712 "c2: purple\n" 1713 "c3: green\n" 1714 "...\n", 1715 /*Ctxt=*/nullptr, 1716 suppressErrorMessages); 1717 yin >> map; 1718 EXPECT_TRUE(!!yin.error()); 1719 } 1720 1721 1722 // 1723 // Test error handling of flow sequence with unknown value 1724 // 1725 TEST(YAMLIO, TestFlagsReadError) { 1726 FlagsMap map; 1727 Input yin("---\n" 1728 "f1: [ big ]\n" 1729 "f2: [ round, hollow ]\n" 1730 "f3: []\n" 1731 "...\n", 1732 /*Ctxt=*/nullptr, 1733 suppressErrorMessages); 1734 yin >> map; 1735 1736 EXPECT_TRUE(!!yin.error()); 1737 } 1738 1739 1740 // 1741 // Test error handling reading built-in uint8_t type 1742 // 1743 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t) 1744 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { 1745 std::vector<uint8_t> seq; 1746 Input yin("---\n" 1747 "- 255\n" 1748 "- 0\n" 1749 "- 257\n" 1750 "...\n", 1751 /*Ctxt=*/nullptr, 1752 suppressErrorMessages); 1753 yin >> seq; 1754 1755 EXPECT_TRUE(!!yin.error()); 1756 } 1757 1758 1759 // 1760 // Test error handling reading built-in uint16_t type 1761 // 1762 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t) 1763 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { 1764 std::vector<uint16_t> seq; 1765 Input yin("---\n" 1766 "- 65535\n" 1767 "- 0\n" 1768 "- 66000\n" 1769 "...\n", 1770 /*Ctxt=*/nullptr, 1771 suppressErrorMessages); 1772 yin >> seq; 1773 1774 EXPECT_TRUE(!!yin.error()); 1775 } 1776 1777 1778 // 1779 // Test error handling reading built-in uint32_t type 1780 // 1781 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t) 1782 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { 1783 std::vector<uint32_t> seq; 1784 Input yin("---\n" 1785 "- 4000000000\n" 1786 "- 0\n" 1787 "- 5000000000\n" 1788 "...\n", 1789 /*Ctxt=*/nullptr, 1790 suppressErrorMessages); 1791 yin >> seq; 1792 1793 EXPECT_TRUE(!!yin.error()); 1794 } 1795 1796 1797 // 1798 // Test error handling reading built-in uint64_t type 1799 // 1800 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t) 1801 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { 1802 std::vector<uint64_t> seq; 1803 Input yin("---\n" 1804 "- 18446744073709551615\n" 1805 "- 0\n" 1806 "- 19446744073709551615\n" 1807 "...\n", 1808 /*Ctxt=*/nullptr, 1809 suppressErrorMessages); 1810 yin >> seq; 1811 1812 EXPECT_TRUE(!!yin.error()); 1813 } 1814 1815 1816 // 1817 // Test error handling reading built-in int8_t type 1818 // 1819 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t) 1820 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { 1821 std::vector<int8_t> seq; 1822 Input yin("---\n" 1823 "- -128\n" 1824 "- 0\n" 1825 "- 127\n" 1826 "- 128\n" 1827 "...\n", 1828 /*Ctxt=*/nullptr, 1829 suppressErrorMessages); 1830 yin >> seq; 1831 1832 EXPECT_TRUE(!!yin.error()); 1833 } 1834 1835 // 1836 // Test error handling reading built-in int8_t type 1837 // 1838 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { 1839 std::vector<int8_t> seq; 1840 Input yin("---\n" 1841 "- -128\n" 1842 "- 0\n" 1843 "- 127\n" 1844 "- -129\n" 1845 "...\n", 1846 /*Ctxt=*/nullptr, 1847 suppressErrorMessages); 1848 yin >> seq; 1849 1850 EXPECT_TRUE(!!yin.error()); 1851 } 1852 1853 1854 // 1855 // Test error handling reading built-in int16_t type 1856 // 1857 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t) 1858 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { 1859 std::vector<int16_t> seq; 1860 Input yin("---\n" 1861 "- 32767\n" 1862 "- 0\n" 1863 "- -32768\n" 1864 "- -32769\n" 1865 "...\n", 1866 /*Ctxt=*/nullptr, 1867 suppressErrorMessages); 1868 yin >> seq; 1869 1870 EXPECT_TRUE(!!yin.error()); 1871 } 1872 1873 1874 // 1875 // Test error handling reading built-in int16_t type 1876 // 1877 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { 1878 std::vector<int16_t> seq; 1879 Input yin("---\n" 1880 "- 32767\n" 1881 "- 0\n" 1882 "- -32768\n" 1883 "- 32768\n" 1884 "...\n", 1885 /*Ctxt=*/nullptr, 1886 suppressErrorMessages); 1887 yin >> seq; 1888 1889 EXPECT_TRUE(!!yin.error()); 1890 } 1891 1892 1893 // 1894 // Test error handling reading built-in int32_t type 1895 // 1896 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t) 1897 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { 1898 std::vector<int32_t> seq; 1899 Input yin("---\n" 1900 "- 2147483647\n" 1901 "- 0\n" 1902 "- -2147483648\n" 1903 "- -2147483649\n" 1904 "...\n", 1905 /*Ctxt=*/nullptr, 1906 suppressErrorMessages); 1907 yin >> seq; 1908 1909 EXPECT_TRUE(!!yin.error()); 1910 } 1911 1912 // 1913 // Test error handling reading built-in int32_t type 1914 // 1915 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { 1916 std::vector<int32_t> seq; 1917 Input yin("---\n" 1918 "- 2147483647\n" 1919 "- 0\n" 1920 "- -2147483648\n" 1921 "- 2147483649\n" 1922 "...\n", 1923 /*Ctxt=*/nullptr, 1924 suppressErrorMessages); 1925 yin >> seq; 1926 1927 EXPECT_TRUE(!!yin.error()); 1928 } 1929 1930 1931 // 1932 // Test error handling reading built-in int64_t type 1933 // 1934 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t) 1935 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { 1936 std::vector<int64_t> seq; 1937 Input yin("---\n" 1938 "- -9223372036854775808\n" 1939 "- 0\n" 1940 "- 9223372036854775807\n" 1941 "- -9223372036854775809\n" 1942 "...\n", 1943 /*Ctxt=*/nullptr, 1944 suppressErrorMessages); 1945 yin >> seq; 1946 1947 EXPECT_TRUE(!!yin.error()); 1948 } 1949 1950 // 1951 // Test error handling reading built-in int64_t type 1952 // 1953 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { 1954 std::vector<int64_t> seq; 1955 Input yin("---\n" 1956 "- -9223372036854775808\n" 1957 "- 0\n" 1958 "- 9223372036854775807\n" 1959 "- 9223372036854775809\n" 1960 "...\n", 1961 /*Ctxt=*/nullptr, 1962 suppressErrorMessages); 1963 yin >> seq; 1964 1965 EXPECT_TRUE(!!yin.error()); 1966 } 1967 1968 // 1969 // Test error handling reading built-in float type 1970 // 1971 LLVM_YAML_IS_SEQUENCE_VECTOR(float) 1972 TEST(YAMLIO, TestReadBuiltInTypesFloatError) { 1973 std::vector<float> seq; 1974 Input yin("---\n" 1975 "- 0.0\n" 1976 "- 1000.1\n" 1977 "- -123.456\n" 1978 "- 1.2.3\n" 1979 "...\n", 1980 /*Ctxt=*/nullptr, 1981 suppressErrorMessages); 1982 yin >> seq; 1983 1984 EXPECT_TRUE(!!yin.error()); 1985 } 1986 1987 // 1988 // Test error handling reading built-in float type 1989 // 1990 LLVM_YAML_IS_SEQUENCE_VECTOR(double) 1991 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { 1992 std::vector<double> seq; 1993 Input yin("---\n" 1994 "- 0.0\n" 1995 "- 1000.1\n" 1996 "- -123.456\n" 1997 "- 1.2.3\n" 1998 "...\n", 1999 /*Ctxt=*/nullptr, 2000 suppressErrorMessages); 2001 yin >> seq; 2002 2003 EXPECT_TRUE(!!yin.error()); 2004 } 2005 2006 // 2007 // Test error handling reading built-in Hex8 type 2008 // 2009 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8) 2010 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { 2011 std::vector<Hex8> seq; 2012 Input yin("---\n" 2013 "- 0x12\n" 2014 "- 0xFE\n" 2015 "- 0x123\n" 2016 "...\n", 2017 /*Ctxt=*/nullptr, 2018 suppressErrorMessages); 2019 yin >> seq; 2020 2021 EXPECT_TRUE(!!yin.error()); 2022 } 2023 2024 2025 // 2026 // Test error handling reading built-in Hex16 type 2027 // 2028 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16) 2029 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { 2030 std::vector<Hex16> seq; 2031 Input yin("---\n" 2032 "- 0x0012\n" 2033 "- 0xFEFF\n" 2034 "- 0x12345\n" 2035 "...\n", 2036 /*Ctxt=*/nullptr, 2037 suppressErrorMessages); 2038 yin >> seq; 2039 2040 EXPECT_TRUE(!!yin.error()); 2041 } 2042 2043 // 2044 // Test error handling reading built-in Hex32 type 2045 // 2046 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32) 2047 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { 2048 std::vector<Hex32> seq; 2049 Input yin("---\n" 2050 "- 0x0012\n" 2051 "- 0xFEFF0000\n" 2052 "- 0x1234556789\n" 2053 "...\n", 2054 /*Ctxt=*/nullptr, 2055 suppressErrorMessages); 2056 yin >> seq; 2057 2058 EXPECT_TRUE(!!yin.error()); 2059 } 2060 2061 // 2062 // Test error handling reading built-in Hex64 type 2063 // 2064 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64) 2065 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { 2066 std::vector<Hex64> seq; 2067 Input yin("---\n" 2068 "- 0x0012\n" 2069 "- 0xFFEEDDCCBBAA9988\n" 2070 "- 0x12345567890ABCDEF0\n" 2071 "...\n", 2072 /*Ctxt=*/nullptr, 2073 suppressErrorMessages); 2074 yin >> seq; 2075 2076 EXPECT_TRUE(!!yin.error()); 2077 } 2078 2079 TEST(YAMLIO, TestMalformedMapFailsGracefully) { 2080 FooBar doc; 2081 { 2082 // We pass the suppressErrorMessages handler to handle the error 2083 // message generated in the constructor of Input. 2084 Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages); 2085 yin >> doc; 2086 EXPECT_TRUE(!!yin.error()); 2087 } 2088 2089 { 2090 Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages); 2091 yin >> doc; 2092 EXPECT_TRUE(!!yin.error()); 2093 } 2094 } 2095 2096 struct OptionalTest { 2097 std::vector<int> Numbers; 2098 }; 2099 2100 struct OptionalTestSeq { 2101 std::vector<OptionalTest> Tests; 2102 }; 2103 2104 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest) 2105 namespace llvm { 2106 namespace yaml { 2107 template <> 2108 struct MappingTraits<OptionalTest> { 2109 static void mapping(IO& IO, OptionalTest &OT) { 2110 IO.mapOptional("Numbers", OT.Numbers); 2111 } 2112 }; 2113 2114 template <> 2115 struct MappingTraits<OptionalTestSeq> { 2116 static void mapping(IO &IO, OptionalTestSeq &OTS) { 2117 IO.mapOptional("Tests", OTS.Tests); 2118 } 2119 }; 2120 } 2121 } 2122 2123 TEST(YAMLIO, SequenceElideTest) { 2124 // Test that writing out a purely optional structure with its fields set to 2125 // default followed by other data is properly read back in. 2126 OptionalTestSeq Seq; 2127 OptionalTest One, Two, Three, Four; 2128 int N[] = {1, 2, 3}; 2129 Three.Numbers.assign(N, N + 3); 2130 Seq.Tests.push_back(One); 2131 Seq.Tests.push_back(Two); 2132 Seq.Tests.push_back(Three); 2133 Seq.Tests.push_back(Four); 2134 2135 std::string intermediate; 2136 { 2137 llvm::raw_string_ostream ostr(intermediate); 2138 Output yout(ostr); 2139 yout << Seq; 2140 } 2141 2142 Input yin(intermediate); 2143 OptionalTestSeq Seq2; 2144 yin >> Seq2; 2145 2146 EXPECT_FALSE(yin.error()); 2147 2148 EXPECT_EQ(4UL, Seq2.Tests.size()); 2149 2150 EXPECT_TRUE(Seq2.Tests[0].Numbers.empty()); 2151 EXPECT_TRUE(Seq2.Tests[1].Numbers.empty()); 2152 2153 EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]); 2154 EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]); 2155 EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]); 2156 2157 EXPECT_TRUE(Seq2.Tests[3].Numbers.empty()); 2158 } 2159 2160 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) { 2161 FooBar doc; 2162 Input yin(""); 2163 yin >> doc; 2164 EXPECT_TRUE(!!yin.error()); 2165 } 2166 2167 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { 2168 OptionalTest doc; 2169 Input yin(""); 2170 yin >> doc; 2171 EXPECT_FALSE(yin.error()); 2172 } 2173 2174 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) { 2175 std::vector<uint8_t> seq; 2176 Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages); 2177 yin >> seq; 2178 2179 EXPECT_FALSE(yin.error()); 2180 EXPECT_TRUE(seq.empty()); 2181 } 2182 2183 struct FlowMap { 2184 llvm::StringRef str1, str2, str3; 2185 FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3) 2186 : str1(str1), str2(str2), str3(str3) {} 2187 }; 2188 2189 struct FlowSeq { 2190 llvm::StringRef str; 2191 FlowSeq(llvm::StringRef S) : str(S) {} 2192 FlowSeq() = default; 2193 }; 2194 2195 namespace llvm { 2196 namespace yaml { 2197 template <> 2198 struct MappingTraits<FlowMap> { 2199 static void mapping(IO &io, FlowMap &fm) { 2200 io.mapRequired("str1", fm.str1); 2201 io.mapRequired("str2", fm.str2); 2202 io.mapRequired("str3", fm.str3); 2203 } 2204 2205 static const bool flow = true; 2206 }; 2207 2208 template <> 2209 struct ScalarTraits<FlowSeq> { 2210 static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) { 2211 out << value.str; 2212 } 2213 static StringRef input(StringRef scalar, void*, FlowSeq &value) { 2214 value.str = scalar; 2215 return ""; 2216 } 2217 2218 static bool mustQuote(StringRef S) { return false; } 2219 }; 2220 } 2221 } 2222 2223 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq) 2224 2225 TEST(YAMLIO, TestWrapFlow) { 2226 std::string out; 2227 llvm::raw_string_ostream ostr(out); 2228 FlowMap Map("This is str1", "This is str2", "This is str3"); 2229 std::vector<FlowSeq> Seq; 2230 Seq.emplace_back("This is str1"); 2231 Seq.emplace_back("This is str2"); 2232 Seq.emplace_back("This is str3"); 2233 2234 { 2235 // 20 is just bellow the total length of the first mapping field. 2236 // We should wreap at every element. 2237 Output yout(ostr, nullptr, 15); 2238 2239 yout << Map; 2240 ostr.flush(); 2241 EXPECT_EQ(out, 2242 "---\n" 2243 "{ str1: This is str1, \n" 2244 " str2: This is str2, \n" 2245 " str3: This is str3 }\n" 2246 "...\n"); 2247 out.clear(); 2248 2249 yout << Seq; 2250 ostr.flush(); 2251 EXPECT_EQ(out, 2252 "---\n" 2253 "[ This is str1, \n" 2254 " This is str2, \n" 2255 " This is str3 ]\n" 2256 "...\n"); 2257 out.clear(); 2258 } 2259 { 2260 // 25 will allow the second field to be output on the first line. 2261 Output yout(ostr, nullptr, 25); 2262 2263 yout << Map; 2264 ostr.flush(); 2265 EXPECT_EQ(out, 2266 "---\n" 2267 "{ str1: This is str1, str2: This is str2, \n" 2268 " str3: This is str3 }\n" 2269 "...\n"); 2270 out.clear(); 2271 2272 yout << Seq; 2273 ostr.flush(); 2274 EXPECT_EQ(out, 2275 "---\n" 2276 "[ This is str1, This is str2, \n" 2277 " This is str3 ]\n" 2278 "...\n"); 2279 out.clear(); 2280 } 2281 { 2282 // 0 means no wrapping. 2283 Output yout(ostr, nullptr, 0); 2284 2285 yout << Map; 2286 ostr.flush(); 2287 EXPECT_EQ(out, 2288 "---\n" 2289 "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n" 2290 "...\n"); 2291 out.clear(); 2292 2293 yout << Seq; 2294 ostr.flush(); 2295 EXPECT_EQ(out, 2296 "---\n" 2297 "[ This is str1, This is str2, This is str3 ]\n" 2298 "...\n"); 2299 out.clear(); 2300 } 2301 } 2302