1 //===- unittest/Support/YAMLIOTest.cpp ------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/BitmaskEnum.h" 10 #include "llvm/ADT/StringMap.h" 11 #include "llvm/ADT/StringRef.h" 12 #include "llvm/ADT/StringSwitch.h" 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/Support/Casting.h" 15 #include "llvm/Support/Endian.h" 16 #include "llvm/Support/Format.h" 17 #include "llvm/Support/YAMLTraits.h" 18 #include "gmock/gmock.h" 19 #include "gtest/gtest.h" 20 21 using llvm::yaml::Hex16; 22 using llvm::yaml::Hex32; 23 using llvm::yaml::Hex64; 24 using llvm::yaml::Hex8; 25 using llvm::yaml::Input; 26 using llvm::yaml::IO; 27 using llvm::yaml::isNumeric; 28 using llvm::yaml::MappingNormalization; 29 using llvm::yaml::MappingTraits; 30 using llvm::yaml::Output; 31 using llvm::yaml::ScalarTraits; 32 using ::testing::StartsWith; 33 34 35 36 37 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { 38 } 39 40 41 42 //===----------------------------------------------------------------------===// 43 // Test MappingTraits 44 //===----------------------------------------------------------------------===// 45 46 struct FooBar { 47 int foo; 48 int bar; 49 }; 50 typedef std::vector<FooBar> FooBarSequence; 51 52 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar) 53 54 struct FooBarContainer { 55 FooBarSequence fbs; 56 }; 57 58 namespace llvm { 59 namespace yaml { 60 template <> 61 struct MappingTraits<FooBar> { 62 static void mapping(IO &io, FooBar& fb) { 63 io.mapRequired("foo", fb.foo); 64 io.mapRequired("bar", fb.bar); 65 } 66 }; 67 68 template <> struct MappingTraits<FooBarContainer> { 69 static void mapping(IO &io, FooBarContainer &fb) { 70 io.mapRequired("fbs", fb.fbs); 71 } 72 }; 73 } 74 } 75 76 77 // 78 // Test the reading of a yaml mapping 79 // 80 TEST(YAMLIO, TestMapRead) { 81 FooBar doc; 82 { 83 Input yin("---\nfoo: 3\nbar: 5\n...\n"); 84 yin >> doc; 85 86 EXPECT_FALSE(yin.error()); 87 EXPECT_EQ(doc.foo, 3); 88 EXPECT_EQ(doc.bar, 5); 89 } 90 91 { 92 Input yin("{foo: 3, bar: 5}"); 93 yin >> doc; 94 95 EXPECT_FALSE(yin.error()); 96 EXPECT_EQ(doc.foo, 3); 97 EXPECT_EQ(doc.bar, 5); 98 } 99 } 100 101 TEST(YAMLIO, TestMalformedMapRead) { 102 FooBar doc; 103 Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages); 104 yin >> doc; 105 EXPECT_TRUE(!!yin.error()); 106 } 107 108 // 109 // Test the reading of a yaml sequence of mappings 110 // 111 TEST(YAMLIO, TestSequenceMapRead) { 112 FooBarSequence seq; 113 Input yin("---\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n"); 114 yin >> seq; 115 116 EXPECT_FALSE(yin.error()); 117 EXPECT_EQ(seq.size(), 2UL); 118 FooBar& map1 = seq[0]; 119 FooBar& map2 = seq[1]; 120 EXPECT_EQ(map1.foo, 3); 121 EXPECT_EQ(map1.bar, 5); 122 EXPECT_EQ(map2.foo, 7); 123 EXPECT_EQ(map2.bar, 9); 124 } 125 126 // 127 // Test the reading of a map containing a yaml sequence of mappings 128 // 129 TEST(YAMLIO, TestContainerSequenceMapRead) { 130 { 131 FooBarContainer cont; 132 Input yin2("---\nfbs:\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n"); 133 yin2 >> cont; 134 135 EXPECT_FALSE(yin2.error()); 136 EXPECT_EQ(cont.fbs.size(), 2UL); 137 EXPECT_EQ(cont.fbs[0].foo, 3); 138 EXPECT_EQ(cont.fbs[0].bar, 5); 139 EXPECT_EQ(cont.fbs[1].foo, 7); 140 EXPECT_EQ(cont.fbs[1].bar, 9); 141 } 142 143 { 144 FooBarContainer cont; 145 Input yin("---\nfbs:\n...\n"); 146 yin >> cont; 147 // Okay: Empty node represents an empty array. 148 EXPECT_FALSE(yin.error()); 149 EXPECT_EQ(cont.fbs.size(), 0UL); 150 } 151 152 { 153 FooBarContainer cont; 154 Input yin("---\nfbs: !!null null\n...\n"); 155 yin >> cont; 156 // Okay: null represents an empty array. 157 EXPECT_FALSE(yin.error()); 158 EXPECT_EQ(cont.fbs.size(), 0UL); 159 } 160 161 { 162 FooBarContainer cont; 163 Input yin("---\nfbs: ~\n...\n"); 164 yin >> cont; 165 // Okay: null represents an empty array. 166 EXPECT_FALSE(yin.error()); 167 EXPECT_EQ(cont.fbs.size(), 0UL); 168 } 169 170 { 171 FooBarContainer cont; 172 Input yin("---\nfbs: null\n...\n"); 173 yin >> cont; 174 // Okay: null represents an empty array. 175 EXPECT_FALSE(yin.error()); 176 EXPECT_EQ(cont.fbs.size(), 0UL); 177 } 178 } 179 180 // 181 // Test the reading of a map containing a malformed yaml sequence 182 // 183 TEST(YAMLIO, TestMalformedContainerSequenceMapRead) { 184 { 185 FooBarContainer cont; 186 Input yin("---\nfbs:\n foo: 3\n bar: 5\n...\n", nullptr, 187 suppressErrorMessages); 188 yin >> cont; 189 // Error: fbs is not a sequence. 190 EXPECT_TRUE(!!yin.error()); 191 EXPECT_EQ(cont.fbs.size(), 0UL); 192 } 193 194 { 195 FooBarContainer cont; 196 Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages); 197 yin >> cont; 198 // This should be an error. 199 EXPECT_TRUE(!!yin.error()); 200 EXPECT_EQ(cont.fbs.size(), 0UL); 201 } 202 } 203 204 // 205 // Test writing then reading back a sequence of mappings 206 // 207 TEST(YAMLIO, TestSequenceMapWriteAndRead) { 208 std::string intermediate; 209 { 210 FooBar entry1; 211 entry1.foo = 10; 212 entry1.bar = -3; 213 FooBar entry2; 214 entry2.foo = 257; 215 entry2.bar = 0; 216 FooBarSequence seq; 217 seq.push_back(entry1); 218 seq.push_back(entry2); 219 220 llvm::raw_string_ostream ostr(intermediate); 221 Output yout(ostr); 222 yout << seq; 223 } 224 225 { 226 Input yin(intermediate); 227 FooBarSequence seq2; 228 yin >> seq2; 229 230 EXPECT_FALSE(yin.error()); 231 EXPECT_EQ(seq2.size(), 2UL); 232 FooBar& map1 = seq2[0]; 233 FooBar& map2 = seq2[1]; 234 EXPECT_EQ(map1.foo, 10); 235 EXPECT_EQ(map1.bar, -3); 236 EXPECT_EQ(map2.foo, 257); 237 EXPECT_EQ(map2.bar, 0); 238 } 239 } 240 241 // 242 // Test reading the entire struct as an enum. 243 // 244 245 struct FooBarEnum { 246 int Foo; 247 int Bar; 248 bool operator==(const FooBarEnum &R) const { 249 return Foo == R.Foo && Bar == R.Bar; 250 } 251 }; 252 253 namespace llvm { 254 namespace yaml { 255 template <> struct MappingTraits<FooBarEnum> { 256 static void enumInput(IO &io, FooBarEnum &Val) { 257 io.enumCase(Val, "OnlyFoo", FooBarEnum({1, 0})); 258 io.enumCase(Val, "OnlyBar", FooBarEnum({0, 1})); 259 } 260 static void mapping(IO &io, FooBarEnum &Val) { 261 io.mapOptional("Foo", Val.Foo); 262 io.mapOptional("Bar", Val.Bar); 263 } 264 }; 265 } // namespace yaml 266 } // namespace llvm 267 268 TEST(YAMLIO, TestMapEnumRead) { 269 FooBarEnum Doc; 270 { 271 Input Yin("OnlyFoo"); 272 Yin >> Doc; 273 EXPECT_FALSE(Yin.error()); 274 EXPECT_EQ(Doc.Foo, 1); 275 EXPECT_EQ(Doc.Bar, 0); 276 } 277 { 278 Input Yin("OnlyBar"); 279 Yin >> Doc; 280 EXPECT_FALSE(Yin.error()); 281 EXPECT_EQ(Doc.Foo, 0); 282 EXPECT_EQ(Doc.Bar, 1); 283 } 284 { 285 Input Yin("{Foo: 3, Bar: 5}"); 286 Yin >> Doc; 287 EXPECT_FALSE(Yin.error()); 288 EXPECT_EQ(Doc.Foo, 3); 289 EXPECT_EQ(Doc.Bar, 5); 290 } 291 } 292 293 // 294 // Test YAML filename handling. 295 // 296 static void testErrorFilename(const llvm::SMDiagnostic &Error, void *) { 297 EXPECT_EQ(Error.getFilename(), "foo.yaml"); 298 } 299 300 TEST(YAMLIO, TestGivenFilename) { 301 auto Buffer = llvm::MemoryBuffer::getMemBuffer("{ x: 42 }", "foo.yaml"); 302 Input yin(*Buffer, nullptr, testErrorFilename); 303 FooBar Value; 304 yin >> Value; 305 306 EXPECT_TRUE(!!yin.error()); 307 } 308 309 struct WithStringField { 310 std::string str1; 311 std::string str2; 312 std::string str3; 313 }; 314 315 namespace llvm { 316 namespace yaml { 317 template <> struct MappingTraits<WithStringField> { 318 static void mapping(IO &io, WithStringField &fb) { 319 io.mapRequired("str1", fb.str1); 320 io.mapRequired("str2", fb.str2); 321 io.mapRequired("str3", fb.str3); 322 } 323 }; 324 } // namespace yaml 325 } // namespace llvm 326 327 TEST(YAMLIO, MultilineStrings) { 328 WithStringField Original; 329 Original.str1 = "a multiline string\nfoobarbaz"; 330 Original.str2 = "another one\rfoobarbaz"; 331 Original.str3 = "a one-line string"; 332 333 std::string Serialized; 334 { 335 llvm::raw_string_ostream OS(Serialized); 336 Output YOut(OS); 337 YOut << Original; 338 } 339 auto Expected = "---\n" 340 "str1: \"a multiline string\\nfoobarbaz\"\n" 341 "str2: \"another one\\rfoobarbaz\"\n" 342 "str3: a one-line string\n" 343 "...\n"; 344 ASSERT_EQ(Serialized, Expected); 345 346 // Also check it parses back without the errors. 347 WithStringField Deserialized; 348 { 349 Input YIn(Serialized); 350 YIn >> Deserialized; 351 ASSERT_FALSE(YIn.error()) 352 << "Parsing error occurred during deserialization. Serialized string:\n" 353 << Serialized; 354 } 355 EXPECT_EQ(Original.str1, Deserialized.str1); 356 EXPECT_EQ(Original.str2, Deserialized.str2); 357 EXPECT_EQ(Original.str3, Deserialized.str3); 358 } 359 360 TEST(YAMLIO, NoQuotesForTab) { 361 WithStringField WithTab; 362 WithTab.str1 = "aba\tcaba"; 363 std::string Serialized; 364 { 365 llvm::raw_string_ostream OS(Serialized); 366 Output YOut(OS); 367 YOut << WithTab; 368 } 369 auto ExpectedPrefix = "---\n" 370 "str1: aba\tcaba\n"; 371 EXPECT_THAT(Serialized, StartsWith(ExpectedPrefix)); 372 } 373 374 //===----------------------------------------------------------------------===// 375 // Test built-in types 376 //===----------------------------------------------------------------------===// 377 378 struct BuiltInTypes { 379 llvm::StringRef str; 380 std::string stdstr; 381 uint64_t u64; 382 uint32_t u32; 383 uint16_t u16; 384 uint8_t u8; 385 bool b; 386 int64_t s64; 387 int32_t s32; 388 int16_t s16; 389 int8_t s8; 390 float f; 391 double d; 392 Hex8 h8; 393 Hex16 h16; 394 Hex32 h32; 395 Hex64 h64; 396 }; 397 398 namespace llvm { 399 namespace yaml { 400 template <> 401 struct MappingTraits<BuiltInTypes> { 402 static void mapping(IO &io, BuiltInTypes& bt) { 403 io.mapRequired("str", bt.str); 404 io.mapRequired("stdstr", bt.stdstr); 405 io.mapRequired("u64", bt.u64); 406 io.mapRequired("u32", bt.u32); 407 io.mapRequired("u16", bt.u16); 408 io.mapRequired("u8", bt.u8); 409 io.mapRequired("b", bt.b); 410 io.mapRequired("s64", bt.s64); 411 io.mapRequired("s32", bt.s32); 412 io.mapRequired("s16", bt.s16); 413 io.mapRequired("s8", bt.s8); 414 io.mapRequired("f", bt.f); 415 io.mapRequired("d", bt.d); 416 io.mapRequired("h8", bt.h8); 417 io.mapRequired("h16", bt.h16); 418 io.mapRequired("h32", bt.h32); 419 io.mapRequired("h64", bt.h64); 420 } 421 }; 422 } 423 } 424 425 426 // 427 // Test the reading of all built-in scalar conversions 428 // 429 TEST(YAMLIO, TestReadBuiltInTypes) { 430 BuiltInTypes map; 431 Input yin("---\n" 432 "str: hello there\n" 433 "stdstr: hello where?\n" 434 "u64: 5000000000\n" 435 "u32: 4000000000\n" 436 "u16: 65000\n" 437 "u8: 255\n" 438 "b: false\n" 439 "s64: -5000000000\n" 440 "s32: -2000000000\n" 441 "s16: -32000\n" 442 "s8: -127\n" 443 "f: 137.125\n" 444 "d: -2.8625\n" 445 "h8: 0xFF\n" 446 "h16: 0x8765\n" 447 "h32: 0xFEDCBA98\n" 448 "h64: 0xFEDCBA9876543210\n" 449 "...\n"); 450 yin >> map; 451 452 EXPECT_FALSE(yin.error()); 453 EXPECT_EQ(map.str, "hello there"); 454 EXPECT_EQ(map.stdstr, "hello where?"); 455 EXPECT_EQ(map.u64, 5000000000ULL); 456 EXPECT_EQ(map.u32, 4000000000U); 457 EXPECT_EQ(map.u16, 65000); 458 EXPECT_EQ(map.u8, 255); 459 EXPECT_EQ(map.b, false); 460 EXPECT_EQ(map.s64, -5000000000LL); 461 EXPECT_EQ(map.s32, -2000000000L); 462 EXPECT_EQ(map.s16, -32000); 463 EXPECT_EQ(map.s8, -127); 464 EXPECT_EQ(map.f, 137.125); 465 EXPECT_EQ(map.d, -2.8625); 466 EXPECT_EQ(map.h8, Hex8(255)); 467 EXPECT_EQ(map.h16, Hex16(0x8765)); 468 EXPECT_EQ(map.h32, Hex32(0xFEDCBA98)); 469 EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL)); 470 } 471 472 473 // 474 // Test writing then reading back all built-in scalar types 475 // 476 TEST(YAMLIO, TestReadWriteBuiltInTypes) { 477 std::string intermediate; 478 { 479 BuiltInTypes map; 480 map.str = "one two"; 481 map.stdstr = "three four"; 482 map.u64 = 6000000000ULL; 483 map.u32 = 3000000000U; 484 map.u16 = 50000; 485 map.u8 = 254; 486 map.b = true; 487 map.s64 = -6000000000LL; 488 map.s32 = -2000000000; 489 map.s16 = -32000; 490 map.s8 = -128; 491 map.f = 3.25; 492 map.d = -2.8625; 493 map.h8 = 254; 494 map.h16 = 50000; 495 map.h32 = 3000000000U; 496 map.h64 = 6000000000LL; 497 498 llvm::raw_string_ostream ostr(intermediate); 499 Output yout(ostr); 500 yout << map; 501 } 502 503 { 504 Input yin(intermediate); 505 BuiltInTypes map; 506 yin >> map; 507 508 EXPECT_FALSE(yin.error()); 509 EXPECT_EQ(map.str, "one two"); 510 EXPECT_EQ(map.stdstr, "three four"); 511 EXPECT_EQ(map.u64, 6000000000ULL); 512 EXPECT_EQ(map.u32, 3000000000U); 513 EXPECT_EQ(map.u16, 50000); 514 EXPECT_EQ(map.u8, 254); 515 EXPECT_EQ(map.b, true); 516 EXPECT_EQ(map.s64, -6000000000LL); 517 EXPECT_EQ(map.s32, -2000000000L); 518 EXPECT_EQ(map.s16, -32000); 519 EXPECT_EQ(map.s8, -128); 520 EXPECT_EQ(map.f, 3.25); 521 EXPECT_EQ(map.d, -2.8625); 522 EXPECT_EQ(map.h8, Hex8(254)); 523 EXPECT_EQ(map.h16, Hex16(50000)); 524 EXPECT_EQ(map.h32, Hex32(3000000000U)); 525 EXPECT_EQ(map.h64, Hex64(6000000000LL)); 526 } 527 } 528 529 //===----------------------------------------------------------------------===// 530 // Test endian-aware types 531 //===----------------------------------------------------------------------===// 532 533 struct EndianTypes { 534 typedef llvm::support::detail::packed_endian_specific_integral< 535 float, llvm::support::little, llvm::support::unaligned> 536 ulittle_float; 537 typedef llvm::support::detail::packed_endian_specific_integral< 538 double, llvm::support::little, llvm::support::unaligned> 539 ulittle_double; 540 541 llvm::support::ulittle64_t u64; 542 llvm::support::ulittle32_t u32; 543 llvm::support::ulittle16_t u16; 544 llvm::support::little64_t s64; 545 llvm::support::little32_t s32; 546 llvm::support::little16_t s16; 547 ulittle_float f; 548 ulittle_double d; 549 }; 550 551 namespace llvm { 552 namespace yaml { 553 template <> struct MappingTraits<EndianTypes> { 554 static void mapping(IO &io, EndianTypes &et) { 555 io.mapRequired("u64", et.u64); 556 io.mapRequired("u32", et.u32); 557 io.mapRequired("u16", et.u16); 558 io.mapRequired("s64", et.s64); 559 io.mapRequired("s32", et.s32); 560 io.mapRequired("s16", et.s16); 561 io.mapRequired("f", et.f); 562 io.mapRequired("d", et.d); 563 } 564 }; 565 } 566 } 567 568 // 569 // Test the reading of all endian scalar conversions 570 // 571 TEST(YAMLIO, TestReadEndianTypes) { 572 EndianTypes map; 573 Input yin("---\n" 574 "u64: 5000000000\n" 575 "u32: 4000000000\n" 576 "u16: 65000\n" 577 "s64: -5000000000\n" 578 "s32: -2000000000\n" 579 "s16: -32000\n" 580 "f: 3.25\n" 581 "d: -2.8625\n" 582 "...\n"); 583 yin >> map; 584 585 EXPECT_FALSE(yin.error()); 586 EXPECT_EQ(map.u64, 5000000000ULL); 587 EXPECT_EQ(map.u32, 4000000000U); 588 EXPECT_EQ(map.u16, 65000); 589 EXPECT_EQ(map.s64, -5000000000LL); 590 EXPECT_EQ(map.s32, -2000000000L); 591 EXPECT_EQ(map.s16, -32000); 592 EXPECT_EQ(map.f, 3.25f); 593 EXPECT_EQ(map.d, -2.8625); 594 } 595 596 // 597 // Test writing then reading back all endian-aware scalar types 598 // 599 TEST(YAMLIO, TestReadWriteEndianTypes) { 600 std::string intermediate; 601 { 602 EndianTypes map; 603 map.u64 = 6000000000ULL; 604 map.u32 = 3000000000U; 605 map.u16 = 50000; 606 map.s64 = -6000000000LL; 607 map.s32 = -2000000000; 608 map.s16 = -32000; 609 map.f = 3.25f; 610 map.d = -2.8625; 611 612 llvm::raw_string_ostream ostr(intermediate); 613 Output yout(ostr); 614 yout << map; 615 } 616 617 { 618 Input yin(intermediate); 619 EndianTypes map; 620 yin >> map; 621 622 EXPECT_FALSE(yin.error()); 623 EXPECT_EQ(map.u64, 6000000000ULL); 624 EXPECT_EQ(map.u32, 3000000000U); 625 EXPECT_EQ(map.u16, 50000); 626 EXPECT_EQ(map.s64, -6000000000LL); 627 EXPECT_EQ(map.s32, -2000000000L); 628 EXPECT_EQ(map.s16, -32000); 629 EXPECT_EQ(map.f, 3.25f); 630 EXPECT_EQ(map.d, -2.8625); 631 } 632 } 633 634 enum class Enum : uint16_t { One, Two }; 635 enum class BitsetEnum : uint16_t { 636 ZeroOne = 0x01, 637 OneZero = 0x10, 638 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ OneZero), 639 }; 640 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 641 struct EndianEnums { 642 llvm::support::little_t<Enum> LittleEnum; 643 llvm::support::big_t<Enum> BigEnum; 644 llvm::support::little_t<BitsetEnum> LittleBitset; 645 llvm::support::big_t<BitsetEnum> BigBitset; 646 }; 647 namespace llvm { 648 namespace yaml { 649 template <> struct ScalarEnumerationTraits<Enum> { 650 static void enumeration(IO &io, Enum &E) { 651 io.enumCase(E, "One", Enum::One); 652 io.enumCase(E, "Two", Enum::Two); 653 } 654 }; 655 656 template <> struct ScalarBitSetTraits<BitsetEnum> { 657 static void bitset(IO &io, BitsetEnum &E) { 658 io.bitSetCase(E, "ZeroOne", BitsetEnum::ZeroOne); 659 io.bitSetCase(E, "OneZero", BitsetEnum::OneZero); 660 } 661 }; 662 663 template <> struct MappingTraits<EndianEnums> { 664 static void mapping(IO &io, EndianEnums &EE) { 665 io.mapRequired("LittleEnum", EE.LittleEnum); 666 io.mapRequired("BigEnum", EE.BigEnum); 667 io.mapRequired("LittleBitset", EE.LittleBitset); 668 io.mapRequired("BigBitset", EE.BigBitset); 669 } 670 }; 671 } // namespace yaml 672 } // namespace llvm 673 674 TEST(YAMLIO, TestReadEndianEnums) { 675 EndianEnums map; 676 Input yin("---\n" 677 "LittleEnum: One\n" 678 "BigEnum: Two\n" 679 "LittleBitset: [ ZeroOne ]\n" 680 "BigBitset: [ ZeroOne, OneZero ]\n" 681 "...\n"); 682 yin >> map; 683 684 EXPECT_FALSE(yin.error()); 685 EXPECT_EQ(Enum::One, map.LittleEnum); 686 EXPECT_EQ(Enum::Two, map.BigEnum); 687 EXPECT_EQ(BitsetEnum::ZeroOne, map.LittleBitset); 688 EXPECT_EQ(BitsetEnum::ZeroOne | BitsetEnum::OneZero, map.BigBitset); 689 } 690 691 TEST(YAMLIO, TestReadWriteEndianEnums) { 692 std::string intermediate; 693 { 694 EndianEnums map; 695 map.LittleEnum = Enum::Two; 696 map.BigEnum = Enum::One; 697 map.LittleBitset = BitsetEnum::OneZero | BitsetEnum::ZeroOne; 698 map.BigBitset = BitsetEnum::OneZero; 699 700 llvm::raw_string_ostream ostr(intermediate); 701 Output yout(ostr); 702 yout << map; 703 } 704 705 { 706 Input yin(intermediate); 707 EndianEnums map; 708 yin >> map; 709 710 EXPECT_FALSE(yin.error()); 711 EXPECT_EQ(Enum::Two, map.LittleEnum); 712 EXPECT_EQ(Enum::One, map.BigEnum); 713 EXPECT_EQ(BitsetEnum::OneZero | BitsetEnum::ZeroOne, map.LittleBitset); 714 EXPECT_EQ(BitsetEnum::OneZero, map.BigBitset); 715 } 716 } 717 718 struct StringTypes { 719 llvm::StringRef str1; 720 llvm::StringRef str2; 721 llvm::StringRef str3; 722 llvm::StringRef str4; 723 llvm::StringRef str5; 724 llvm::StringRef str6; 725 llvm::StringRef str7; 726 llvm::StringRef str8; 727 llvm::StringRef str9; 728 llvm::StringRef str10; 729 llvm::StringRef str11; 730 std::string stdstr1; 731 std::string stdstr2; 732 std::string stdstr3; 733 std::string stdstr4; 734 std::string stdstr5; 735 std::string stdstr6; 736 std::string stdstr7; 737 std::string stdstr8; 738 std::string stdstr9; 739 std::string stdstr10; 740 std::string stdstr11; 741 std::string stdstr12; 742 std::string stdstr13; 743 }; 744 745 namespace llvm { 746 namespace yaml { 747 template <> 748 struct MappingTraits<StringTypes> { 749 static void mapping(IO &io, StringTypes& st) { 750 io.mapRequired("str1", st.str1); 751 io.mapRequired("str2", st.str2); 752 io.mapRequired("str3", st.str3); 753 io.mapRequired("str4", st.str4); 754 io.mapRequired("str5", st.str5); 755 io.mapRequired("str6", st.str6); 756 io.mapRequired("str7", st.str7); 757 io.mapRequired("str8", st.str8); 758 io.mapRequired("str9", st.str9); 759 io.mapRequired("str10", st.str10); 760 io.mapRequired("str11", st.str11); 761 io.mapRequired("stdstr1", st.stdstr1); 762 io.mapRequired("stdstr2", st.stdstr2); 763 io.mapRequired("stdstr3", st.stdstr3); 764 io.mapRequired("stdstr4", st.stdstr4); 765 io.mapRequired("stdstr5", st.stdstr5); 766 io.mapRequired("stdstr6", st.stdstr6); 767 io.mapRequired("stdstr7", st.stdstr7); 768 io.mapRequired("stdstr8", st.stdstr8); 769 io.mapRequired("stdstr9", st.stdstr9); 770 io.mapRequired("stdstr10", st.stdstr10); 771 io.mapRequired("stdstr11", st.stdstr11); 772 io.mapRequired("stdstr12", st.stdstr12); 773 io.mapRequired("stdstr13", st.stdstr13); 774 } 775 }; 776 } 777 } 778 779 TEST(YAMLIO, TestReadWriteStringTypes) { 780 std::string intermediate; 781 { 782 StringTypes map; 783 map.str1 = "'aaa"; 784 map.str2 = "\"bbb"; 785 map.str3 = "`ccc"; 786 map.str4 = "@ddd"; 787 map.str5 = ""; 788 map.str6 = "0000000004000000"; 789 map.str7 = "true"; 790 map.str8 = "FALSE"; 791 map.str9 = "~"; 792 map.str10 = "0.2e20"; 793 map.str11 = "0x30"; 794 map.stdstr1 = "'eee"; 795 map.stdstr2 = "\"fff"; 796 map.stdstr3 = "`ggg"; 797 map.stdstr4 = "@hhh"; 798 map.stdstr5 = ""; 799 map.stdstr6 = "0000000004000000"; 800 map.stdstr7 = "true"; 801 map.stdstr8 = "FALSE"; 802 map.stdstr9 = "~"; 803 map.stdstr10 = "0.2e20"; 804 map.stdstr11 = "0x30"; 805 map.stdstr12 = "- match"; 806 map.stdstr13.assign("\0a\0b\0", 5); 807 808 llvm::raw_string_ostream ostr(intermediate); 809 Output yout(ostr); 810 yout << map; 811 } 812 813 llvm::StringRef flowOut(intermediate); 814 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa")); 815 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'")); 816 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); 817 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); 818 EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); 819 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n")); 820 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n")); 821 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n")); 822 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n")); 823 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n")); 824 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n")); 825 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'- match'\n")); 826 EXPECT_NE(std::string::npos, flowOut.find("'''eee")); 827 EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); 828 EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); 829 EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); 830 EXPECT_NE(std::string::npos, flowOut.find("''\n")); 831 EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n")); 832 EXPECT_NE(std::string::npos, flowOut.find("\"\\0a\\0b\\0\"")); 833 834 { 835 Input yin(intermediate); 836 StringTypes map; 837 yin >> map; 838 839 EXPECT_FALSE(yin.error()); 840 EXPECT_EQ(map.str1, "'aaa"); 841 EXPECT_EQ(map.str2, "\"bbb"); 842 EXPECT_EQ(map.str3, "`ccc"); 843 EXPECT_EQ(map.str4, "@ddd"); 844 EXPECT_EQ(map.str5, ""); 845 EXPECT_EQ(map.str6, "0000000004000000"); 846 EXPECT_EQ(map.stdstr1, "'eee"); 847 EXPECT_EQ(map.stdstr2, "\"fff"); 848 EXPECT_EQ(map.stdstr3, "`ggg"); 849 EXPECT_EQ(map.stdstr4, "@hhh"); 850 EXPECT_EQ(map.stdstr5, ""); 851 EXPECT_EQ(map.stdstr6, "0000000004000000"); 852 EXPECT_EQ(std::string("\0a\0b\0", 5), map.stdstr13); 853 } 854 } 855 856 //===----------------------------------------------------------------------===// 857 // Test ScalarEnumerationTraits 858 //===----------------------------------------------------------------------===// 859 860 enum Colors { 861 cRed, 862 cBlue, 863 cGreen, 864 cYellow 865 }; 866 867 struct ColorMap { 868 Colors c1; 869 Colors c2; 870 Colors c3; 871 Colors c4; 872 Colors c5; 873 Colors c6; 874 }; 875 876 namespace llvm { 877 namespace yaml { 878 template <> 879 struct ScalarEnumerationTraits<Colors> { 880 static void enumeration(IO &io, Colors &value) { 881 io.enumCase(value, "red", cRed); 882 io.enumCase(value, "blue", cBlue); 883 io.enumCase(value, "green", cGreen); 884 io.enumCase(value, "yellow",cYellow); 885 } 886 }; 887 template <> 888 struct MappingTraits<ColorMap> { 889 static void mapping(IO &io, ColorMap& c) { 890 io.mapRequired("c1", c.c1); 891 io.mapRequired("c2", c.c2); 892 io.mapRequired("c3", c.c3); 893 io.mapOptional("c4", c.c4, cBlue); // supplies default 894 io.mapOptional("c5", c.c5, cYellow); // supplies default 895 io.mapOptional("c6", c.c6, cRed); // supplies default 896 } 897 }; 898 } 899 } 900 901 902 // 903 // Test reading enumerated scalars 904 // 905 TEST(YAMLIO, TestEnumRead) { 906 ColorMap map; 907 Input yin("---\n" 908 "c1: blue\n" 909 "c2: red\n" 910 "c3: green\n" 911 "c5: yellow\n" 912 "...\n"); 913 yin >> map; 914 915 EXPECT_FALSE(yin.error()); 916 EXPECT_EQ(cBlue, map.c1); 917 EXPECT_EQ(cRed, map.c2); 918 EXPECT_EQ(cGreen, map.c3); 919 EXPECT_EQ(cBlue, map.c4); // tests default 920 EXPECT_EQ(cYellow,map.c5); // tests overridden 921 EXPECT_EQ(cRed, map.c6); // tests default 922 } 923 924 925 926 //===----------------------------------------------------------------------===// 927 // Test ScalarBitSetTraits 928 //===----------------------------------------------------------------------===// 929 930 enum MyFlags { 931 flagNone = 0, 932 flagBig = 1 << 0, 933 flagFlat = 1 << 1, 934 flagRound = 1 << 2, 935 flagPointy = 1 << 3 936 }; 937 inline MyFlags operator|(MyFlags a, MyFlags b) { 938 return static_cast<MyFlags>( 939 static_cast<uint32_t>(a) | static_cast<uint32_t>(b)); 940 } 941 942 struct FlagsMap { 943 MyFlags f1; 944 MyFlags f2; 945 MyFlags f3; 946 MyFlags f4; 947 }; 948 949 950 namespace llvm { 951 namespace yaml { 952 template <> 953 struct ScalarBitSetTraits<MyFlags> { 954 static void bitset(IO &io, MyFlags &value) { 955 io.bitSetCase(value, "big", flagBig); 956 io.bitSetCase(value, "flat", flagFlat); 957 io.bitSetCase(value, "round", flagRound); 958 io.bitSetCase(value, "pointy",flagPointy); 959 } 960 }; 961 template <> 962 struct MappingTraits<FlagsMap> { 963 static void mapping(IO &io, FlagsMap& c) { 964 io.mapRequired("f1", c.f1); 965 io.mapRequired("f2", c.f2); 966 io.mapRequired("f3", c.f3); 967 io.mapOptional("f4", c.f4, flagRound); 968 } 969 }; 970 } 971 } 972 973 974 // 975 // Test reading flow sequence representing bit-mask values 976 // 977 TEST(YAMLIO, TestFlagsRead) { 978 FlagsMap map; 979 Input yin("---\n" 980 "f1: [ big ]\n" 981 "f2: [ round, flat ]\n" 982 "f3: []\n" 983 "...\n"); 984 yin >> map; 985 986 EXPECT_FALSE(yin.error()); 987 EXPECT_EQ(flagBig, map.f1); 988 EXPECT_EQ(flagRound|flagFlat, map.f2); 989 EXPECT_EQ(flagNone, map.f3); // check empty set 990 EXPECT_EQ(flagRound, map.f4); // check optional key 991 } 992 993 994 // 995 // Test writing then reading back bit-mask values 996 // 997 TEST(YAMLIO, TestReadWriteFlags) { 998 std::string intermediate; 999 { 1000 FlagsMap map; 1001 map.f1 = flagBig; 1002 map.f2 = flagRound | flagFlat; 1003 map.f3 = flagNone; 1004 map.f4 = flagNone; 1005 1006 llvm::raw_string_ostream ostr(intermediate); 1007 Output yout(ostr); 1008 yout << map; 1009 } 1010 1011 { 1012 Input yin(intermediate); 1013 FlagsMap map2; 1014 yin >> map2; 1015 1016 EXPECT_FALSE(yin.error()); 1017 EXPECT_EQ(flagBig, map2.f1); 1018 EXPECT_EQ(flagRound|flagFlat, map2.f2); 1019 EXPECT_EQ(flagNone, map2.f3); 1020 //EXPECT_EQ(flagRound, map2.f4); // check optional key 1021 } 1022 } 1023 1024 1025 1026 //===----------------------------------------------------------------------===// 1027 // Test ScalarTraits 1028 //===----------------------------------------------------------------------===// 1029 1030 struct MyCustomType { 1031 int length; 1032 int width; 1033 }; 1034 1035 struct MyCustomTypeMap { 1036 MyCustomType f1; 1037 MyCustomType f2; 1038 int f3; 1039 }; 1040 1041 1042 namespace llvm { 1043 namespace yaml { 1044 template <> 1045 struct MappingTraits<MyCustomTypeMap> { 1046 static void mapping(IO &io, MyCustomTypeMap& s) { 1047 io.mapRequired("f1", s.f1); 1048 io.mapRequired("f2", s.f2); 1049 io.mapRequired("f3", s.f3); 1050 } 1051 }; 1052 // MyCustomType is formatted as a yaml scalar. A value of 1053 // {length=3, width=4} would be represented in yaml as "3 by 4". 1054 template<> 1055 struct ScalarTraits<MyCustomType> { 1056 static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) { 1057 out << llvm::format("%d by %d", value.length, value.width); 1058 } 1059 static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) { 1060 size_t byStart = scalar.find("by"); 1061 if ( byStart != StringRef::npos ) { 1062 StringRef lenStr = scalar.slice(0, byStart); 1063 lenStr = lenStr.rtrim(); 1064 if ( lenStr.getAsInteger(0, value.length) ) { 1065 return "malformed length"; 1066 } 1067 StringRef widthStr = scalar.drop_front(byStart+2); 1068 widthStr = widthStr.ltrim(); 1069 if ( widthStr.getAsInteger(0, value.width) ) { 1070 return "malformed width"; 1071 } 1072 return StringRef(); 1073 } 1074 else { 1075 return "malformed by"; 1076 } 1077 } 1078 static QuotingType mustQuote(StringRef) { return QuotingType::Single; } 1079 }; 1080 } 1081 } 1082 1083 1084 // 1085 // Test writing then reading back custom values 1086 // 1087 TEST(YAMLIO, TestReadWriteMyCustomType) { 1088 std::string intermediate; 1089 { 1090 MyCustomTypeMap map; 1091 map.f1.length = 1; 1092 map.f1.width = 4; 1093 map.f2.length = 100; 1094 map.f2.width = 400; 1095 map.f3 = 10; 1096 1097 llvm::raw_string_ostream ostr(intermediate); 1098 Output yout(ostr); 1099 yout << map; 1100 } 1101 1102 { 1103 Input yin(intermediate); 1104 MyCustomTypeMap map2; 1105 yin >> map2; 1106 1107 EXPECT_FALSE(yin.error()); 1108 EXPECT_EQ(1, map2.f1.length); 1109 EXPECT_EQ(4, map2.f1.width); 1110 EXPECT_EQ(100, map2.f2.length); 1111 EXPECT_EQ(400, map2.f2.width); 1112 EXPECT_EQ(10, map2.f3); 1113 } 1114 } 1115 1116 1117 //===----------------------------------------------------------------------===// 1118 // Test BlockScalarTraits 1119 //===----------------------------------------------------------------------===// 1120 1121 struct MultilineStringType { 1122 std::string str; 1123 }; 1124 1125 struct MultilineStringTypeMap { 1126 MultilineStringType name; 1127 MultilineStringType description; 1128 MultilineStringType ingredients; 1129 MultilineStringType recipes; 1130 MultilineStringType warningLabels; 1131 MultilineStringType documentation; 1132 int price; 1133 }; 1134 1135 namespace llvm { 1136 namespace yaml { 1137 template <> 1138 struct MappingTraits<MultilineStringTypeMap> { 1139 static void mapping(IO &io, MultilineStringTypeMap& s) { 1140 io.mapRequired("name", s.name); 1141 io.mapRequired("description", s.description); 1142 io.mapRequired("ingredients", s.ingredients); 1143 io.mapRequired("recipes", s.recipes); 1144 io.mapRequired("warningLabels", s.warningLabels); 1145 io.mapRequired("documentation", s.documentation); 1146 io.mapRequired("price", s.price); 1147 } 1148 }; 1149 1150 // MultilineStringType is formatted as a yaml block literal scalar. A value of 1151 // "Hello\nWorld" would be represented in yaml as 1152 // | 1153 // Hello 1154 // World 1155 template <> 1156 struct BlockScalarTraits<MultilineStringType> { 1157 static void output(const MultilineStringType &value, void *ctxt, 1158 llvm::raw_ostream &out) { 1159 out << value.str; 1160 } 1161 static StringRef input(StringRef scalar, void *ctxt, 1162 MultilineStringType &value) { 1163 value.str = scalar.str(); 1164 return StringRef(); 1165 } 1166 }; 1167 } 1168 } 1169 1170 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType) 1171 1172 // 1173 // Test writing then reading back custom values 1174 // 1175 TEST(YAMLIO, TestReadWriteMultilineStringType) { 1176 std::string intermediate; 1177 { 1178 MultilineStringTypeMap map; 1179 map.name.str = "An Item"; 1180 map.description.str = "Hello\nWorld"; 1181 map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n"; 1182 map.recipes.str = "\n\nTest 1\n\n\n"; 1183 map.warningLabels.str = ""; 1184 map.documentation.str = "\n\n"; 1185 map.price = 350; 1186 1187 llvm::raw_string_ostream ostr(intermediate); 1188 Output yout(ostr); 1189 yout << map; 1190 } 1191 { 1192 Input yin(intermediate); 1193 MultilineStringTypeMap map2; 1194 yin >> map2; 1195 1196 EXPECT_FALSE(yin.error()); 1197 EXPECT_EQ(map2.name.str, "An Item\n"); 1198 EXPECT_EQ(map2.description.str, "Hello\nWorld\n"); 1199 EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n"); 1200 EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n"); 1201 EXPECT_TRUE(map2.warningLabels.str.empty()); 1202 EXPECT_TRUE(map2.documentation.str.empty()); 1203 EXPECT_EQ(map2.price, 350); 1204 } 1205 } 1206 1207 // 1208 // Test writing then reading back custom values 1209 // 1210 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) { 1211 std::string intermediate; 1212 { 1213 std::vector<MultilineStringType> documents; 1214 MultilineStringType doc; 1215 doc.str = "Hello\nWorld"; 1216 documents.push_back(doc); 1217 1218 llvm::raw_string_ostream ostr(intermediate); 1219 Output yout(ostr); 1220 yout << documents; 1221 1222 // Verify that the block scalar header was written out on the same line 1223 // as the document marker. 1224 EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |")); 1225 } 1226 { 1227 Input yin(intermediate); 1228 std::vector<MultilineStringType> documents2; 1229 yin >> documents2; 1230 1231 EXPECT_FALSE(yin.error()); 1232 EXPECT_EQ(documents2.size(), size_t(1)); 1233 EXPECT_EQ(documents2[0].str, "Hello\nWorld\n"); 1234 } 1235 } 1236 1237 TEST(YAMLIO, TestReadWriteBlockScalarValue) { 1238 std::string intermediate; 1239 { 1240 MultilineStringType doc; 1241 doc.str = "Just a block\nscalar doc"; 1242 1243 llvm::raw_string_ostream ostr(intermediate); 1244 Output yout(ostr); 1245 yout << doc; 1246 } 1247 { 1248 Input yin(intermediate); 1249 MultilineStringType doc; 1250 yin >> doc; 1251 1252 EXPECT_FALSE(yin.error()); 1253 EXPECT_EQ(doc.str, "Just a block\nscalar doc\n"); 1254 } 1255 } 1256 1257 //===----------------------------------------------------------------------===// 1258 // Test flow sequences 1259 //===----------------------------------------------------------------------===// 1260 1261 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber) 1262 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber) 1263 LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, MyString) 1264 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyString) 1265 1266 namespace llvm { 1267 namespace yaml { 1268 template<> 1269 struct ScalarTraits<MyNumber> { 1270 static void output(const MyNumber &value, void *, llvm::raw_ostream &out) { 1271 out << value; 1272 } 1273 1274 static StringRef input(StringRef scalar, void *, MyNumber &value) { 1275 long long n; 1276 if ( getAsSignedInteger(scalar, 0, n) ) 1277 return "invalid number"; 1278 value = n; 1279 return StringRef(); 1280 } 1281 1282 static QuotingType mustQuote(StringRef) { return QuotingType::None; } 1283 }; 1284 1285 template <> struct ScalarTraits<MyString> { 1286 using Impl = ScalarTraits<StringRef>; 1287 static void output(const MyString &V, void *Ctx, raw_ostream &OS) { 1288 Impl::output(V, Ctx, OS); 1289 } 1290 static StringRef input(StringRef S, void *Ctx, MyString &V) { 1291 return Impl::input(S, Ctx, V.value); 1292 } 1293 static QuotingType mustQuote(StringRef S) { 1294 return Impl::mustQuote(S); 1295 } 1296 }; 1297 } 1298 } 1299 1300 struct NameAndNumbers { 1301 llvm::StringRef name; 1302 std::vector<MyString> strings; 1303 std::vector<MyNumber> single; 1304 std::vector<MyNumber> numbers; 1305 }; 1306 1307 namespace llvm { 1308 namespace yaml { 1309 template <> 1310 struct MappingTraits<NameAndNumbers> { 1311 static void mapping(IO &io, NameAndNumbers& nn) { 1312 io.mapRequired("name", nn.name); 1313 io.mapRequired("strings", nn.strings); 1314 io.mapRequired("single", nn.single); 1315 io.mapRequired("numbers", nn.numbers); 1316 } 1317 }; 1318 } 1319 } 1320 1321 typedef std::vector<MyNumber> MyNumberFlowSequence; 1322 1323 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence) 1324 1325 struct NameAndNumbersFlow { 1326 llvm::StringRef name; 1327 std::vector<MyNumberFlowSequence> sequenceOfNumbers; 1328 }; 1329 1330 namespace llvm { 1331 namespace yaml { 1332 template <> 1333 struct MappingTraits<NameAndNumbersFlow> { 1334 static void mapping(IO &io, NameAndNumbersFlow& nn) { 1335 io.mapRequired("name", nn.name); 1336 io.mapRequired("sequenceOfNumbers", nn.sequenceOfNumbers); 1337 } 1338 }; 1339 } 1340 } 1341 1342 // 1343 // Test writing then reading back custom values 1344 // 1345 TEST(YAMLIO, TestReadWriteMyFlowSequence) { 1346 std::string intermediate; 1347 { 1348 NameAndNumbers map; 1349 map.name = "hello"; 1350 map.strings.push_back(llvm::StringRef("one")); 1351 map.strings.push_back(llvm::StringRef("two")); 1352 map.single.push_back(1); 1353 map.numbers.push_back(10); 1354 map.numbers.push_back(-30); 1355 map.numbers.push_back(1024); 1356 1357 llvm::raw_string_ostream ostr(intermediate); 1358 Output yout(ostr); 1359 yout << map; 1360 1361 // Verify sequences were written in flow style 1362 ostr.flush(); 1363 llvm::StringRef flowOut(intermediate); 1364 EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two")); 1365 EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024")); 1366 } 1367 1368 { 1369 Input yin(intermediate); 1370 NameAndNumbers map2; 1371 yin >> map2; 1372 1373 EXPECT_FALSE(yin.error()); 1374 EXPECT_TRUE(map2.name.equals("hello")); 1375 EXPECT_EQ(map2.strings.size(), 2UL); 1376 EXPECT_TRUE(map2.strings[0].value.equals("one")); 1377 EXPECT_TRUE(map2.strings[1].value.equals("two")); 1378 EXPECT_EQ(map2.single.size(), 1UL); 1379 EXPECT_EQ(1, map2.single[0]); 1380 EXPECT_EQ(map2.numbers.size(), 3UL); 1381 EXPECT_EQ(10, map2.numbers[0]); 1382 EXPECT_EQ(-30, map2.numbers[1]); 1383 EXPECT_EQ(1024, map2.numbers[2]); 1384 } 1385 } 1386 1387 1388 // 1389 // Test writing then reading back a sequence of flow sequences. 1390 // 1391 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) { 1392 std::string intermediate; 1393 { 1394 NameAndNumbersFlow map; 1395 map.name = "hello"; 1396 MyNumberFlowSequence single = { 0 }; 1397 MyNumberFlowSequence numbers = { 12, 1, -512 }; 1398 map.sequenceOfNumbers.push_back(single); 1399 map.sequenceOfNumbers.push_back(numbers); 1400 map.sequenceOfNumbers.push_back(MyNumberFlowSequence()); 1401 1402 llvm::raw_string_ostream ostr(intermediate); 1403 Output yout(ostr); 1404 yout << map; 1405 1406 // Verify sequences were written in flow style 1407 // and that the parent sequence used '-'. 1408 ostr.flush(); 1409 llvm::StringRef flowOut(intermediate); 1410 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]")); 1411 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]")); 1412 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ ]")); 1413 } 1414 1415 { 1416 Input yin(intermediate); 1417 NameAndNumbersFlow map2; 1418 yin >> map2; 1419 1420 EXPECT_FALSE(yin.error()); 1421 EXPECT_TRUE(map2.name.equals("hello")); 1422 EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL); 1423 EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL); 1424 EXPECT_EQ(0, map2.sequenceOfNumbers[0][0]); 1425 EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL); 1426 EXPECT_EQ(12, map2.sequenceOfNumbers[1][0]); 1427 EXPECT_EQ(1, map2.sequenceOfNumbers[1][1]); 1428 EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]); 1429 EXPECT_TRUE(map2.sequenceOfNumbers[2].empty()); 1430 } 1431 } 1432 1433 //===----------------------------------------------------------------------===// 1434 // Test normalizing/denormalizing 1435 //===----------------------------------------------------------------------===// 1436 1437 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds) 1438 1439 typedef std::vector<TotalSeconds> SecondsSequence; 1440 1441 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds) 1442 1443 1444 namespace llvm { 1445 namespace yaml { 1446 template <> 1447 struct MappingTraits<TotalSeconds> { 1448 1449 class NormalizedSeconds { 1450 public: 1451 NormalizedSeconds(IO &io) 1452 : hours(0), minutes(0), seconds(0) { 1453 } 1454 NormalizedSeconds(IO &, TotalSeconds &secs) 1455 : hours(secs/3600), 1456 minutes((secs - (hours*3600))/60), 1457 seconds(secs % 60) { 1458 } 1459 TotalSeconds denormalize(IO &) { 1460 return TotalSeconds(hours*3600 + minutes*60 + seconds); 1461 } 1462 1463 uint32_t hours; 1464 uint8_t minutes; 1465 uint8_t seconds; 1466 }; 1467 1468 static void mapping(IO &io, TotalSeconds &secs) { 1469 MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs); 1470 1471 io.mapOptional("hours", keys->hours, 0); 1472 io.mapOptional("minutes", keys->minutes, 0); 1473 io.mapRequired("seconds", keys->seconds); 1474 } 1475 }; 1476 } 1477 } 1478 1479 1480 // 1481 // Test the reading of a yaml sequence of mappings 1482 // 1483 TEST(YAMLIO, TestReadMySecondsSequence) { 1484 SecondsSequence seq; 1485 Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n"); 1486 yin >> seq; 1487 1488 EXPECT_FALSE(yin.error()); 1489 EXPECT_EQ(seq.size(), 2UL); 1490 EXPECT_EQ(seq[0], 3605U); 1491 EXPECT_EQ(seq[1], 59U); 1492 } 1493 1494 1495 // 1496 // Test writing then reading back custom values 1497 // 1498 TEST(YAMLIO, TestReadWriteMySecondsSequence) { 1499 std::string intermediate; 1500 { 1501 SecondsSequence seq; 1502 seq.push_back(4000); 1503 seq.push_back(500); 1504 seq.push_back(59); 1505 1506 llvm::raw_string_ostream ostr(intermediate); 1507 Output yout(ostr); 1508 yout << seq; 1509 } 1510 { 1511 Input yin(intermediate); 1512 SecondsSequence seq2; 1513 yin >> seq2; 1514 1515 EXPECT_FALSE(yin.error()); 1516 EXPECT_EQ(seq2.size(), 3UL); 1517 EXPECT_EQ(seq2[0], 4000U); 1518 EXPECT_EQ(seq2[1], 500U); 1519 EXPECT_EQ(seq2[2], 59U); 1520 } 1521 } 1522 1523 1524 //===----------------------------------------------------------------------===// 1525 // Test dynamic typing 1526 //===----------------------------------------------------------------------===// 1527 1528 enum AFlags { 1529 a1, 1530 a2, 1531 a3 1532 }; 1533 1534 enum BFlags { 1535 b1, 1536 b2, 1537 b3 1538 }; 1539 1540 enum Kind { 1541 kindA, 1542 kindB 1543 }; 1544 1545 struct KindAndFlags { 1546 KindAndFlags() : kind(kindA), flags(0) { } 1547 KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { } 1548 Kind kind; 1549 uint32_t flags; 1550 }; 1551 1552 typedef std::vector<KindAndFlags> KindAndFlagsSequence; 1553 1554 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags) 1555 1556 namespace llvm { 1557 namespace yaml { 1558 template <> 1559 struct ScalarEnumerationTraits<AFlags> { 1560 static void enumeration(IO &io, AFlags &value) { 1561 io.enumCase(value, "a1", a1); 1562 io.enumCase(value, "a2", a2); 1563 io.enumCase(value, "a3", a3); 1564 } 1565 }; 1566 template <> 1567 struct ScalarEnumerationTraits<BFlags> { 1568 static void enumeration(IO &io, BFlags &value) { 1569 io.enumCase(value, "b1", b1); 1570 io.enumCase(value, "b2", b2); 1571 io.enumCase(value, "b3", b3); 1572 } 1573 }; 1574 template <> 1575 struct ScalarEnumerationTraits<Kind> { 1576 static void enumeration(IO &io, Kind &value) { 1577 io.enumCase(value, "A", kindA); 1578 io.enumCase(value, "B", kindB); 1579 } 1580 }; 1581 template <> 1582 struct MappingTraits<KindAndFlags> { 1583 static void mapping(IO &io, KindAndFlags& kf) { 1584 io.mapRequired("kind", kf.kind); 1585 // Type of "flags" field varies depending on "kind" field. 1586 // Use memcpy here to avoid breaking strict aliasing rules. 1587 if (kf.kind == kindA) { 1588 AFlags aflags = static_cast<AFlags>(kf.flags); 1589 io.mapRequired("flags", aflags); 1590 kf.flags = aflags; 1591 } else { 1592 BFlags bflags = static_cast<BFlags>(kf.flags); 1593 io.mapRequired("flags", bflags); 1594 kf.flags = bflags; 1595 } 1596 } 1597 }; 1598 } 1599 } 1600 1601 1602 // 1603 // Test the reading of a yaml sequence dynamic types 1604 // 1605 TEST(YAMLIO, TestReadKindAndFlagsSequence) { 1606 KindAndFlagsSequence seq; 1607 Input yin("---\n - kind: A\n flags: a2\n - kind: B\n flags: b1\n...\n"); 1608 yin >> seq; 1609 1610 EXPECT_FALSE(yin.error()); 1611 EXPECT_EQ(seq.size(), 2UL); 1612 EXPECT_EQ(seq[0].kind, kindA); 1613 EXPECT_EQ(seq[0].flags, (uint32_t)a2); 1614 EXPECT_EQ(seq[1].kind, kindB); 1615 EXPECT_EQ(seq[1].flags, (uint32_t)b1); 1616 } 1617 1618 // 1619 // Test writing then reading back dynamic types 1620 // 1621 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) { 1622 std::string intermediate; 1623 { 1624 KindAndFlagsSequence seq; 1625 seq.push_back(KindAndFlags(kindA,a1)); 1626 seq.push_back(KindAndFlags(kindB,b1)); 1627 seq.push_back(KindAndFlags(kindA,a2)); 1628 seq.push_back(KindAndFlags(kindB,b2)); 1629 seq.push_back(KindAndFlags(kindA,a3)); 1630 1631 llvm::raw_string_ostream ostr(intermediate); 1632 Output yout(ostr); 1633 yout << seq; 1634 } 1635 { 1636 Input yin(intermediate); 1637 KindAndFlagsSequence seq2; 1638 yin >> seq2; 1639 1640 EXPECT_FALSE(yin.error()); 1641 EXPECT_EQ(seq2.size(), 5UL); 1642 EXPECT_EQ(seq2[0].kind, kindA); 1643 EXPECT_EQ(seq2[0].flags, (uint32_t)a1); 1644 EXPECT_EQ(seq2[1].kind, kindB); 1645 EXPECT_EQ(seq2[1].flags, (uint32_t)b1); 1646 EXPECT_EQ(seq2[2].kind, kindA); 1647 EXPECT_EQ(seq2[2].flags, (uint32_t)a2); 1648 EXPECT_EQ(seq2[3].kind, kindB); 1649 EXPECT_EQ(seq2[3].flags, (uint32_t)b2); 1650 EXPECT_EQ(seq2[4].kind, kindA); 1651 EXPECT_EQ(seq2[4].flags, (uint32_t)a3); 1652 } 1653 } 1654 1655 1656 //===----------------------------------------------------------------------===// 1657 // Test document list 1658 //===----------------------------------------------------------------------===// 1659 1660 struct FooBarMap { 1661 int foo; 1662 int bar; 1663 }; 1664 typedef std::vector<FooBarMap> FooBarMapDocumentList; 1665 1666 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap) 1667 1668 1669 namespace llvm { 1670 namespace yaml { 1671 template <> 1672 struct MappingTraits<FooBarMap> { 1673 static void mapping(IO &io, FooBarMap& fb) { 1674 io.mapRequired("foo", fb.foo); 1675 io.mapRequired("bar", fb.bar); 1676 } 1677 }; 1678 } 1679 } 1680 1681 1682 // 1683 // Test the reading of a yaml mapping 1684 // 1685 TEST(YAMLIO, TestDocRead) { 1686 FooBarMap doc; 1687 Input yin("---\nfoo: 3\nbar: 5\n...\n"); 1688 yin >> doc; 1689 1690 EXPECT_FALSE(yin.error()); 1691 EXPECT_EQ(doc.foo, 3); 1692 EXPECT_EQ(doc.bar,5); 1693 } 1694 1695 1696 1697 // 1698 // Test writing then reading back a sequence of mappings 1699 // 1700 TEST(YAMLIO, TestSequenceDocListWriteAndRead) { 1701 std::string intermediate; 1702 { 1703 FooBarMap doc1; 1704 doc1.foo = 10; 1705 doc1.bar = -3; 1706 FooBarMap doc2; 1707 doc2.foo = 257; 1708 doc2.bar = 0; 1709 std::vector<FooBarMap> docList; 1710 docList.push_back(doc1); 1711 docList.push_back(doc2); 1712 1713 llvm::raw_string_ostream ostr(intermediate); 1714 Output yout(ostr); 1715 yout << docList; 1716 } 1717 1718 1719 { 1720 Input yin(intermediate); 1721 std::vector<FooBarMap> docList2; 1722 yin >> docList2; 1723 1724 EXPECT_FALSE(yin.error()); 1725 EXPECT_EQ(docList2.size(), 2UL); 1726 FooBarMap& map1 = docList2[0]; 1727 FooBarMap& map2 = docList2[1]; 1728 EXPECT_EQ(map1.foo, 10); 1729 EXPECT_EQ(map1.bar, -3); 1730 EXPECT_EQ(map2.foo, 257); 1731 EXPECT_EQ(map2.bar, 0); 1732 } 1733 } 1734 1735 //===----------------------------------------------------------------------===// 1736 // Test document tags 1737 //===----------------------------------------------------------------------===// 1738 1739 struct MyDouble { 1740 MyDouble() : value(0.0) { } 1741 MyDouble(double x) : value(x) { } 1742 double value; 1743 }; 1744 1745 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble) 1746 1747 1748 namespace llvm { 1749 namespace yaml { 1750 template <> 1751 struct MappingTraits<MyDouble> { 1752 static void mapping(IO &io, MyDouble &d) { 1753 if (io.mapTag("!decimal", true)) { 1754 mappingDecimal(io, d); 1755 } else if (io.mapTag("!fraction")) { 1756 mappingFraction(io, d); 1757 } 1758 } 1759 static void mappingDecimal(IO &io, MyDouble &d) { 1760 io.mapRequired("value", d.value); 1761 } 1762 static void mappingFraction(IO &io, MyDouble &d) { 1763 double num, denom; 1764 io.mapRequired("numerator", num); 1765 io.mapRequired("denominator", denom); 1766 // convert fraction to double 1767 d.value = num/denom; 1768 } 1769 }; 1770 } 1771 } 1772 1773 1774 // 1775 // Test the reading of two different tagged yaml documents. 1776 // 1777 TEST(YAMLIO, TestTaggedDocuments) { 1778 std::vector<MyDouble> docList; 1779 Input yin("--- !decimal\nvalue: 3.0\n" 1780 "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n"); 1781 yin >> docList; 1782 EXPECT_FALSE(yin.error()); 1783 EXPECT_EQ(docList.size(), 2UL); 1784 EXPECT_EQ(docList[0].value, 3.0); 1785 EXPECT_EQ(docList[1].value, 4.5); 1786 } 1787 1788 1789 1790 // 1791 // Test writing then reading back tagged documents 1792 // 1793 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) { 1794 std::string intermediate; 1795 { 1796 MyDouble a(10.25); 1797 MyDouble b(-3.75); 1798 std::vector<MyDouble> docList; 1799 docList.push_back(a); 1800 docList.push_back(b); 1801 1802 llvm::raw_string_ostream ostr(intermediate); 1803 Output yout(ostr); 1804 yout << docList; 1805 } 1806 1807 { 1808 Input yin(intermediate); 1809 std::vector<MyDouble> docList2; 1810 yin >> docList2; 1811 1812 EXPECT_FALSE(yin.error()); 1813 EXPECT_EQ(docList2.size(), 2UL); 1814 EXPECT_EQ(docList2[0].value, 10.25); 1815 EXPECT_EQ(docList2[1].value, -3.75); 1816 } 1817 } 1818 1819 1820 //===----------------------------------------------------------------------===// 1821 // Test mapping validation 1822 //===----------------------------------------------------------------------===// 1823 1824 struct MyValidation { 1825 double value; 1826 }; 1827 1828 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation) 1829 1830 namespace llvm { 1831 namespace yaml { 1832 template <> 1833 struct MappingTraits<MyValidation> { 1834 static void mapping(IO &io, MyValidation &d) { 1835 io.mapRequired("value", d.value); 1836 } 1837 static std::string validate(IO &io, MyValidation &d) { 1838 if (d.value < 0) 1839 return "negative value"; 1840 return {}; 1841 } 1842 }; 1843 } 1844 } 1845 1846 1847 // 1848 // Test that validate() is called and complains about the negative value. 1849 // 1850 TEST(YAMLIO, TestValidatingInput) { 1851 std::vector<MyValidation> docList; 1852 Input yin("--- \nvalue: 3.0\n" 1853 "--- \nvalue: -1.0\n...\n", 1854 nullptr, suppressErrorMessages); 1855 yin >> docList; 1856 EXPECT_TRUE(!!yin.error()); 1857 } 1858 1859 //===----------------------------------------------------------------------===// 1860 // Test flow mapping 1861 //===----------------------------------------------------------------------===// 1862 1863 struct FlowFooBar { 1864 int foo; 1865 int bar; 1866 1867 FlowFooBar() : foo(0), bar(0) {} 1868 FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {} 1869 }; 1870 1871 typedef std::vector<FlowFooBar> FlowFooBarSequence; 1872 1873 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar) 1874 1875 struct FlowFooBarDoc { 1876 FlowFooBar attribute; 1877 FlowFooBarSequence seq; 1878 }; 1879 1880 namespace llvm { 1881 namespace yaml { 1882 template <> 1883 struct MappingTraits<FlowFooBar> { 1884 static void mapping(IO &io, FlowFooBar &fb) { 1885 io.mapRequired("foo", fb.foo); 1886 io.mapRequired("bar", fb.bar); 1887 } 1888 1889 static const bool flow = true; 1890 }; 1891 1892 template <> 1893 struct MappingTraits<FlowFooBarDoc> { 1894 static void mapping(IO &io, FlowFooBarDoc &fb) { 1895 io.mapRequired("attribute", fb.attribute); 1896 io.mapRequired("seq", fb.seq); 1897 } 1898 }; 1899 } 1900 } 1901 1902 // 1903 // Test writing then reading back custom mappings 1904 // 1905 TEST(YAMLIO, TestReadWriteMyFlowMapping) { 1906 std::string intermediate; 1907 { 1908 FlowFooBarDoc doc; 1909 doc.attribute = FlowFooBar(42, 907); 1910 doc.seq.push_back(FlowFooBar(1, 2)); 1911 doc.seq.push_back(FlowFooBar(0, 0)); 1912 doc.seq.push_back(FlowFooBar(-1, 1024)); 1913 1914 llvm::raw_string_ostream ostr(intermediate); 1915 Output yout(ostr); 1916 yout << doc; 1917 1918 // Verify that mappings were written in flow style 1919 ostr.flush(); 1920 llvm::StringRef flowOut(intermediate); 1921 EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }")); 1922 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }")); 1923 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }")); 1924 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }")); 1925 } 1926 1927 { 1928 Input yin(intermediate); 1929 FlowFooBarDoc doc2; 1930 yin >> doc2; 1931 1932 EXPECT_FALSE(yin.error()); 1933 EXPECT_EQ(doc2.attribute.foo, 42); 1934 EXPECT_EQ(doc2.attribute.bar, 907); 1935 EXPECT_EQ(doc2.seq.size(), 3UL); 1936 EXPECT_EQ(doc2.seq[0].foo, 1); 1937 EXPECT_EQ(doc2.seq[0].bar, 2); 1938 EXPECT_EQ(doc2.seq[1].foo, 0); 1939 EXPECT_EQ(doc2.seq[1].bar, 0); 1940 EXPECT_EQ(doc2.seq[2].foo, -1); 1941 EXPECT_EQ(doc2.seq[2].bar, 1024); 1942 } 1943 } 1944 1945 //===----------------------------------------------------------------------===// 1946 // Test error handling 1947 //===----------------------------------------------------------------------===// 1948 1949 // 1950 // Test error handling of unknown enumerated scalar 1951 // 1952 TEST(YAMLIO, TestColorsReadError) { 1953 ColorMap map; 1954 Input yin("---\n" 1955 "c1: blue\n" 1956 "c2: purple\n" 1957 "c3: green\n" 1958 "...\n", 1959 /*Ctxt=*/nullptr, 1960 suppressErrorMessages); 1961 yin >> map; 1962 EXPECT_TRUE(!!yin.error()); 1963 } 1964 1965 1966 // 1967 // Test error handling of flow sequence with unknown value 1968 // 1969 TEST(YAMLIO, TestFlagsReadError) { 1970 FlagsMap map; 1971 Input yin("---\n" 1972 "f1: [ big ]\n" 1973 "f2: [ round, hollow ]\n" 1974 "f3: []\n" 1975 "...\n", 1976 /*Ctxt=*/nullptr, 1977 suppressErrorMessages); 1978 yin >> map; 1979 1980 EXPECT_TRUE(!!yin.error()); 1981 } 1982 1983 1984 // 1985 // Test error handling reading built-in uint8_t type 1986 // 1987 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { 1988 std::vector<uint8_t> seq; 1989 Input yin("---\n" 1990 "- 255\n" 1991 "- 0\n" 1992 "- 257\n" 1993 "...\n", 1994 /*Ctxt=*/nullptr, 1995 suppressErrorMessages); 1996 yin >> seq; 1997 1998 EXPECT_TRUE(!!yin.error()); 1999 } 2000 2001 2002 // 2003 // Test error handling reading built-in uint16_t type 2004 // 2005 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { 2006 std::vector<uint16_t> seq; 2007 Input yin("---\n" 2008 "- 65535\n" 2009 "- 0\n" 2010 "- 66000\n" 2011 "...\n", 2012 /*Ctxt=*/nullptr, 2013 suppressErrorMessages); 2014 yin >> seq; 2015 2016 EXPECT_TRUE(!!yin.error()); 2017 } 2018 2019 2020 // 2021 // Test error handling reading built-in uint32_t type 2022 // 2023 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { 2024 std::vector<uint32_t> seq; 2025 Input yin("---\n" 2026 "- 4000000000\n" 2027 "- 0\n" 2028 "- 5000000000\n" 2029 "...\n", 2030 /*Ctxt=*/nullptr, 2031 suppressErrorMessages); 2032 yin >> seq; 2033 2034 EXPECT_TRUE(!!yin.error()); 2035 } 2036 2037 2038 // 2039 // Test error handling reading built-in uint64_t type 2040 // 2041 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { 2042 std::vector<uint64_t> seq; 2043 Input yin("---\n" 2044 "- 18446744073709551615\n" 2045 "- 0\n" 2046 "- 19446744073709551615\n" 2047 "...\n", 2048 /*Ctxt=*/nullptr, 2049 suppressErrorMessages); 2050 yin >> seq; 2051 2052 EXPECT_TRUE(!!yin.error()); 2053 } 2054 2055 2056 // 2057 // Test error handling reading built-in int8_t type 2058 // 2059 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { 2060 std::vector<int8_t> seq; 2061 Input yin("---\n" 2062 "- -128\n" 2063 "- 0\n" 2064 "- 127\n" 2065 "- 128\n" 2066 "...\n", 2067 /*Ctxt=*/nullptr, 2068 suppressErrorMessages); 2069 yin >> seq; 2070 2071 EXPECT_TRUE(!!yin.error()); 2072 } 2073 2074 // 2075 // Test error handling reading built-in int8_t type 2076 // 2077 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { 2078 std::vector<int8_t> seq; 2079 Input yin("---\n" 2080 "- -128\n" 2081 "- 0\n" 2082 "- 127\n" 2083 "- -129\n" 2084 "...\n", 2085 /*Ctxt=*/nullptr, 2086 suppressErrorMessages); 2087 yin >> seq; 2088 2089 EXPECT_TRUE(!!yin.error()); 2090 } 2091 2092 2093 // 2094 // Test error handling reading built-in int16_t type 2095 // 2096 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { 2097 std::vector<int16_t> seq; 2098 Input yin("---\n" 2099 "- 32767\n" 2100 "- 0\n" 2101 "- -32768\n" 2102 "- -32769\n" 2103 "...\n", 2104 /*Ctxt=*/nullptr, 2105 suppressErrorMessages); 2106 yin >> seq; 2107 2108 EXPECT_TRUE(!!yin.error()); 2109 } 2110 2111 2112 // 2113 // Test error handling reading built-in int16_t type 2114 // 2115 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { 2116 std::vector<int16_t> seq; 2117 Input yin("---\n" 2118 "- 32767\n" 2119 "- 0\n" 2120 "- -32768\n" 2121 "- 32768\n" 2122 "...\n", 2123 /*Ctxt=*/nullptr, 2124 suppressErrorMessages); 2125 yin >> seq; 2126 2127 EXPECT_TRUE(!!yin.error()); 2128 } 2129 2130 2131 // 2132 // Test error handling reading built-in int32_t type 2133 // 2134 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { 2135 std::vector<int32_t> seq; 2136 Input yin("---\n" 2137 "- 2147483647\n" 2138 "- 0\n" 2139 "- -2147483648\n" 2140 "- -2147483649\n" 2141 "...\n", 2142 /*Ctxt=*/nullptr, 2143 suppressErrorMessages); 2144 yin >> seq; 2145 2146 EXPECT_TRUE(!!yin.error()); 2147 } 2148 2149 // 2150 // Test error handling reading built-in int32_t type 2151 // 2152 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { 2153 std::vector<int32_t> seq; 2154 Input yin("---\n" 2155 "- 2147483647\n" 2156 "- 0\n" 2157 "- -2147483648\n" 2158 "- 2147483649\n" 2159 "...\n", 2160 /*Ctxt=*/nullptr, 2161 suppressErrorMessages); 2162 yin >> seq; 2163 2164 EXPECT_TRUE(!!yin.error()); 2165 } 2166 2167 2168 // 2169 // Test error handling reading built-in int64_t type 2170 // 2171 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { 2172 std::vector<int64_t> seq; 2173 Input yin("---\n" 2174 "- -9223372036854775808\n" 2175 "- 0\n" 2176 "- 9223372036854775807\n" 2177 "- -9223372036854775809\n" 2178 "...\n", 2179 /*Ctxt=*/nullptr, 2180 suppressErrorMessages); 2181 yin >> seq; 2182 2183 EXPECT_TRUE(!!yin.error()); 2184 } 2185 2186 // 2187 // Test error handling reading built-in int64_t type 2188 // 2189 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { 2190 std::vector<int64_t> seq; 2191 Input yin("---\n" 2192 "- -9223372036854775808\n" 2193 "- 0\n" 2194 "- 9223372036854775807\n" 2195 "- 9223372036854775809\n" 2196 "...\n", 2197 /*Ctxt=*/nullptr, 2198 suppressErrorMessages); 2199 yin >> seq; 2200 2201 EXPECT_TRUE(!!yin.error()); 2202 } 2203 2204 // 2205 // Test error handling reading built-in float type 2206 // 2207 TEST(YAMLIO, TestReadBuiltInTypesFloatError) { 2208 std::vector<float> seq; 2209 Input yin("---\n" 2210 "- 0.0\n" 2211 "- 1000.1\n" 2212 "- -123.456\n" 2213 "- 1.2.3\n" 2214 "...\n", 2215 /*Ctxt=*/nullptr, 2216 suppressErrorMessages); 2217 yin >> seq; 2218 2219 EXPECT_TRUE(!!yin.error()); 2220 } 2221 2222 // 2223 // Test error handling reading built-in float type 2224 // 2225 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { 2226 std::vector<double> seq; 2227 Input yin("---\n" 2228 "- 0.0\n" 2229 "- 1000.1\n" 2230 "- -123.456\n" 2231 "- 1.2.3\n" 2232 "...\n", 2233 /*Ctxt=*/nullptr, 2234 suppressErrorMessages); 2235 yin >> seq; 2236 2237 EXPECT_TRUE(!!yin.error()); 2238 } 2239 2240 // 2241 // Test error handling reading built-in Hex8 type 2242 // 2243 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { 2244 std::vector<Hex8> seq; 2245 Input yin("---\n" 2246 "- 0x12\n" 2247 "- 0xFE\n" 2248 "- 0x123\n" 2249 "...\n", 2250 /*Ctxt=*/nullptr, 2251 suppressErrorMessages); 2252 yin >> seq; 2253 EXPECT_TRUE(!!yin.error()); 2254 2255 std::vector<Hex8> seq2; 2256 Input yin2("---\n" 2257 "[ 0x12, 0xFE, 0x123 ]\n" 2258 "...\n", 2259 /*Ctxt=*/nullptr, suppressErrorMessages); 2260 yin2 >> seq2; 2261 EXPECT_TRUE(!!yin2.error()); 2262 2263 EXPECT_EQ(seq.size(), 3u); 2264 EXPECT_EQ(seq.size(), seq2.size()); 2265 for (size_t i = 0; i < seq.size(); ++i) 2266 EXPECT_EQ(seq[i], seq2[i]); 2267 } 2268 2269 2270 // 2271 // Test error handling reading built-in Hex16 type 2272 // 2273 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { 2274 std::vector<Hex16> seq; 2275 Input yin("---\n" 2276 "- 0x0012\n" 2277 "- 0xFEFF\n" 2278 "- 0x12345\n" 2279 "...\n", 2280 /*Ctxt=*/nullptr, 2281 suppressErrorMessages); 2282 yin >> seq; 2283 EXPECT_TRUE(!!yin.error()); 2284 2285 std::vector<Hex16> seq2; 2286 Input yin2("---\n" 2287 "[ 0x0012, 0xFEFF, 0x12345 ]\n" 2288 "...\n", 2289 /*Ctxt=*/nullptr, suppressErrorMessages); 2290 yin2 >> seq2; 2291 EXPECT_TRUE(!!yin2.error()); 2292 2293 EXPECT_EQ(seq.size(), 3u); 2294 EXPECT_EQ(seq.size(), seq2.size()); 2295 for (size_t i = 0; i < seq.size(); ++i) 2296 EXPECT_EQ(seq[i], seq2[i]); 2297 } 2298 2299 // 2300 // Test error handling reading built-in Hex32 type 2301 // 2302 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { 2303 std::vector<Hex32> seq; 2304 Input yin("---\n" 2305 "- 0x0012\n" 2306 "- 0xFEFF0000\n" 2307 "- 0x1234556789\n" 2308 "...\n", 2309 /*Ctxt=*/nullptr, 2310 suppressErrorMessages); 2311 yin >> seq; 2312 2313 EXPECT_TRUE(!!yin.error()); 2314 2315 std::vector<Hex32> seq2; 2316 Input yin2("---\n" 2317 "[ 0x0012, 0xFEFF0000, 0x1234556789 ]\n" 2318 "...\n", 2319 /*Ctxt=*/nullptr, suppressErrorMessages); 2320 yin2 >> seq2; 2321 EXPECT_TRUE(!!yin2.error()); 2322 2323 EXPECT_EQ(seq.size(), 3u); 2324 EXPECT_EQ(seq.size(), seq2.size()); 2325 for (size_t i = 0; i < seq.size(); ++i) 2326 EXPECT_EQ(seq[i], seq2[i]); 2327 } 2328 2329 // 2330 // Test error handling reading built-in Hex64 type 2331 // 2332 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { 2333 std::vector<Hex64> seq; 2334 Input yin("---\n" 2335 "- 0x0012\n" 2336 "- 0xFFEEDDCCBBAA9988\n" 2337 "- 0x12345567890ABCDEF0\n" 2338 "...\n", 2339 /*Ctxt=*/nullptr, 2340 suppressErrorMessages); 2341 yin >> seq; 2342 EXPECT_TRUE(!!yin.error()); 2343 2344 std::vector<Hex64> seq2; 2345 Input yin2("---\n" 2346 "[ 0x0012, 0xFFEEDDCCBBAA9988, 0x12345567890ABCDEF0 ]\n" 2347 "...\n", 2348 /*Ctxt=*/nullptr, suppressErrorMessages); 2349 yin2 >> seq2; 2350 EXPECT_TRUE(!!yin2.error()); 2351 2352 EXPECT_EQ(seq.size(), 3u); 2353 EXPECT_EQ(seq.size(), seq2.size()); 2354 for (size_t i = 0; i < seq.size(); ++i) 2355 EXPECT_EQ(seq[i], seq2[i]); 2356 } 2357 2358 TEST(YAMLIO, TestMalformedMapFailsGracefully) { 2359 FooBar doc; 2360 { 2361 // We pass the suppressErrorMessages handler to handle the error 2362 // message generated in the constructor of Input. 2363 Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages); 2364 yin >> doc; 2365 EXPECT_TRUE(!!yin.error()); 2366 } 2367 2368 { 2369 Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages); 2370 yin >> doc; 2371 EXPECT_TRUE(!!yin.error()); 2372 } 2373 } 2374 2375 struct OptionalTest { 2376 std::vector<int> Numbers; 2377 }; 2378 2379 struct OptionalTestSeq { 2380 std::vector<OptionalTest> Tests; 2381 }; 2382 2383 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest) 2384 namespace llvm { 2385 namespace yaml { 2386 template <> 2387 struct MappingTraits<OptionalTest> { 2388 static void mapping(IO& IO, OptionalTest &OT) { 2389 IO.mapOptional("Numbers", OT.Numbers); 2390 } 2391 }; 2392 2393 template <> 2394 struct MappingTraits<OptionalTestSeq> { 2395 static void mapping(IO &IO, OptionalTestSeq &OTS) { 2396 IO.mapOptional("Tests", OTS.Tests); 2397 } 2398 }; 2399 } 2400 } 2401 2402 TEST(YAMLIO, SequenceElideTest) { 2403 // Test that writing out a purely optional structure with its fields set to 2404 // default followed by other data is properly read back in. 2405 OptionalTestSeq Seq; 2406 OptionalTest One, Two, Three, Four; 2407 int N[] = {1, 2, 3}; 2408 Three.Numbers.assign(N, N + 3); 2409 Seq.Tests.push_back(One); 2410 Seq.Tests.push_back(Two); 2411 Seq.Tests.push_back(Three); 2412 Seq.Tests.push_back(Four); 2413 2414 std::string intermediate; 2415 { 2416 llvm::raw_string_ostream ostr(intermediate); 2417 Output yout(ostr); 2418 yout << Seq; 2419 } 2420 2421 Input yin(intermediate); 2422 OptionalTestSeq Seq2; 2423 yin >> Seq2; 2424 2425 EXPECT_FALSE(yin.error()); 2426 2427 EXPECT_EQ(4UL, Seq2.Tests.size()); 2428 2429 EXPECT_TRUE(Seq2.Tests[0].Numbers.empty()); 2430 EXPECT_TRUE(Seq2.Tests[1].Numbers.empty()); 2431 2432 EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]); 2433 EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]); 2434 EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]); 2435 2436 EXPECT_TRUE(Seq2.Tests[3].Numbers.empty()); 2437 } 2438 2439 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) { 2440 FooBar doc; 2441 Input yin(""); 2442 yin >> doc; 2443 EXPECT_TRUE(!!yin.error()); 2444 } 2445 2446 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { 2447 OptionalTest doc; 2448 Input yin(""); 2449 yin >> doc; 2450 EXPECT_FALSE(yin.error()); 2451 } 2452 2453 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) { 2454 std::vector<uint8_t> seq; 2455 Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages); 2456 yin >> seq; 2457 2458 EXPECT_FALSE(yin.error()); 2459 EXPECT_TRUE(seq.empty()); 2460 } 2461 2462 struct FlowMap { 2463 llvm::StringRef str1, str2, str3; 2464 FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3) 2465 : str1(str1), str2(str2), str3(str3) {} 2466 }; 2467 2468 struct FlowSeq { 2469 llvm::StringRef str; 2470 FlowSeq(llvm::StringRef S) : str(S) {} 2471 FlowSeq() = default; 2472 }; 2473 2474 namespace llvm { 2475 namespace yaml { 2476 template <> 2477 struct MappingTraits<FlowMap> { 2478 static void mapping(IO &io, FlowMap &fm) { 2479 io.mapRequired("str1", fm.str1); 2480 io.mapRequired("str2", fm.str2); 2481 io.mapRequired("str3", fm.str3); 2482 } 2483 2484 static const bool flow = true; 2485 }; 2486 2487 template <> 2488 struct ScalarTraits<FlowSeq> { 2489 static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) { 2490 out << value.str; 2491 } 2492 static StringRef input(StringRef scalar, void*, FlowSeq &value) { 2493 value.str = scalar; 2494 return ""; 2495 } 2496 2497 static QuotingType mustQuote(StringRef S) { return QuotingType::None; } 2498 }; 2499 } 2500 } 2501 2502 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq) 2503 2504 TEST(YAMLIO, TestWrapFlow) { 2505 std::string out; 2506 llvm::raw_string_ostream ostr(out); 2507 FlowMap Map("This is str1", "This is str2", "This is str3"); 2508 std::vector<FlowSeq> Seq; 2509 Seq.emplace_back("This is str1"); 2510 Seq.emplace_back("This is str2"); 2511 Seq.emplace_back("This is str3"); 2512 2513 { 2514 // 20 is just bellow the total length of the first mapping field. 2515 // We should wreap at every element. 2516 Output yout(ostr, nullptr, 15); 2517 2518 yout << Map; 2519 ostr.flush(); 2520 EXPECT_EQ(out, 2521 "---\n" 2522 "{ str1: This is str1, \n" 2523 " str2: This is str2, \n" 2524 " str3: This is str3 }\n" 2525 "...\n"); 2526 out.clear(); 2527 2528 yout << Seq; 2529 ostr.flush(); 2530 EXPECT_EQ(out, 2531 "---\n" 2532 "[ This is str1, \n" 2533 " This is str2, \n" 2534 " This is str3 ]\n" 2535 "...\n"); 2536 out.clear(); 2537 } 2538 { 2539 // 25 will allow the second field to be output on the first line. 2540 Output yout(ostr, nullptr, 25); 2541 2542 yout << Map; 2543 ostr.flush(); 2544 EXPECT_EQ(out, 2545 "---\n" 2546 "{ str1: This is str1, str2: This is str2, \n" 2547 " str3: This is str3 }\n" 2548 "...\n"); 2549 out.clear(); 2550 2551 yout << Seq; 2552 ostr.flush(); 2553 EXPECT_EQ(out, 2554 "---\n" 2555 "[ This is str1, This is str2, \n" 2556 " This is str3 ]\n" 2557 "...\n"); 2558 out.clear(); 2559 } 2560 { 2561 // 0 means no wrapping. 2562 Output yout(ostr, nullptr, 0); 2563 2564 yout << Map; 2565 ostr.flush(); 2566 EXPECT_EQ(out, 2567 "---\n" 2568 "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n" 2569 "...\n"); 2570 out.clear(); 2571 2572 yout << Seq; 2573 ostr.flush(); 2574 EXPECT_EQ(out, 2575 "---\n" 2576 "[ This is str1, This is str2, This is str3 ]\n" 2577 "...\n"); 2578 out.clear(); 2579 } 2580 } 2581 2582 struct MappingContext { 2583 int A = 0; 2584 }; 2585 struct SimpleMap { 2586 int B = 0; 2587 int C = 0; 2588 }; 2589 2590 struct NestedMap { 2591 NestedMap(MappingContext &Context) : Context(Context) {} 2592 SimpleMap Simple; 2593 MappingContext &Context; 2594 }; 2595 2596 namespace llvm { 2597 namespace yaml { 2598 template <> struct MappingContextTraits<SimpleMap, MappingContext> { 2599 static void mapping(IO &io, SimpleMap &sm, MappingContext &Context) { 2600 io.mapRequired("B", sm.B); 2601 io.mapRequired("C", sm.C); 2602 ++Context.A; 2603 io.mapRequired("Context", Context.A); 2604 } 2605 }; 2606 2607 template <> struct MappingTraits<NestedMap> { 2608 static void mapping(IO &io, NestedMap &nm) { 2609 io.mapRequired("Simple", nm.Simple, nm.Context); 2610 } 2611 }; 2612 } 2613 } 2614 2615 TEST(YAMLIO, TestMapWithContext) { 2616 MappingContext Context; 2617 NestedMap Nested(Context); 2618 std::string out; 2619 llvm::raw_string_ostream ostr(out); 2620 2621 Output yout(ostr, nullptr, 15); 2622 2623 yout << Nested; 2624 ostr.flush(); 2625 EXPECT_EQ(1, Context.A); 2626 EXPECT_EQ("---\n" 2627 "Simple:\n" 2628 " B: 0\n" 2629 " C: 0\n" 2630 " Context: 1\n" 2631 "...\n", 2632 out); 2633 2634 out.clear(); 2635 2636 Nested.Simple.B = 2; 2637 Nested.Simple.C = 3; 2638 yout << Nested; 2639 ostr.flush(); 2640 EXPECT_EQ(2, Context.A); 2641 EXPECT_EQ("---\n" 2642 "Simple:\n" 2643 " B: 2\n" 2644 " C: 3\n" 2645 " Context: 2\n" 2646 "...\n", 2647 out); 2648 out.clear(); 2649 } 2650 2651 LLVM_YAML_IS_STRING_MAP(int) 2652 2653 TEST(YAMLIO, TestCustomMapping) { 2654 std::map<std::string, int> x; 2655 2656 std::string out; 2657 llvm::raw_string_ostream ostr(out); 2658 Output xout(ostr, nullptr, 0); 2659 2660 xout << x; 2661 ostr.flush(); 2662 EXPECT_EQ("---\n" 2663 "{}\n" 2664 "...\n", 2665 out); 2666 2667 x["foo"] = 1; 2668 x["bar"] = 2; 2669 2670 out.clear(); 2671 xout << x; 2672 ostr.flush(); 2673 EXPECT_EQ("---\n" 2674 "bar: 2\n" 2675 "foo: 1\n" 2676 "...\n", 2677 out); 2678 2679 Input yin(out); 2680 std::map<std::string, int> y; 2681 yin >> y; 2682 EXPECT_EQ(2ul, y.size()); 2683 EXPECT_EQ(1, y["foo"]); 2684 EXPECT_EQ(2, y["bar"]); 2685 } 2686 2687 LLVM_YAML_IS_STRING_MAP(FooBar) 2688 2689 TEST(YAMLIO, TestCustomMappingStruct) { 2690 std::map<std::string, FooBar> x; 2691 x["foo"].foo = 1; 2692 x["foo"].bar = 2; 2693 x["bar"].foo = 3; 2694 x["bar"].bar = 4; 2695 2696 std::string out; 2697 llvm::raw_string_ostream ostr(out); 2698 Output xout(ostr, nullptr, 0); 2699 2700 xout << x; 2701 ostr.flush(); 2702 EXPECT_EQ("---\n" 2703 "bar:\n" 2704 " foo: 3\n" 2705 " bar: 4\n" 2706 "foo:\n" 2707 " foo: 1\n" 2708 " bar: 2\n" 2709 "...\n", 2710 out); 2711 2712 Input yin(out); 2713 std::map<std::string, FooBar> y; 2714 yin >> y; 2715 EXPECT_EQ(2ul, y.size()); 2716 EXPECT_EQ(1, y["foo"].foo); 2717 EXPECT_EQ(2, y["foo"].bar); 2718 EXPECT_EQ(3, y["bar"].foo); 2719 EXPECT_EQ(4, y["bar"].bar); 2720 } 2721 2722 struct FooBarMapMap { 2723 std::map<std::string, FooBar> fbm; 2724 }; 2725 2726 namespace llvm { 2727 namespace yaml { 2728 template <> struct MappingTraits<FooBarMapMap> { 2729 static void mapping(IO &io, FooBarMapMap &x) { 2730 io.mapRequired("fbm", x.fbm); 2731 } 2732 }; 2733 } 2734 } 2735 2736 TEST(YAMLIO, TestEmptyMapWrite) { 2737 FooBarMapMap cont; 2738 std::string str; 2739 llvm::raw_string_ostream OS(str); 2740 Output yout(OS); 2741 yout << cont; 2742 EXPECT_EQ(OS.str(), "---\nfbm: {}\n...\n"); 2743 } 2744 2745 TEST(YAMLIO, TestEmptySequenceWrite) { 2746 { 2747 FooBarContainer cont; 2748 std::string str; 2749 llvm::raw_string_ostream OS(str); 2750 Output yout(OS); 2751 yout << cont; 2752 EXPECT_EQ(OS.str(), "---\nfbs: []\n...\n"); 2753 } 2754 2755 { 2756 FooBarSequence seq; 2757 std::string str; 2758 llvm::raw_string_ostream OS(str); 2759 Output yout(OS); 2760 yout << seq; 2761 EXPECT_EQ(OS.str(), "---\n[]\n...\n"); 2762 } 2763 } 2764 2765 static void TestEscaped(llvm::StringRef Input, llvm::StringRef Expected) { 2766 std::string out; 2767 llvm::raw_string_ostream ostr(out); 2768 Output xout(ostr, nullptr, 0); 2769 2770 llvm::yaml::EmptyContext Ctx; 2771 yamlize(xout, Input, true, Ctx); 2772 2773 ostr.flush(); 2774 2775 // Make a separate StringRef so we get nice byte-by-byte output. 2776 llvm::StringRef Got(out); 2777 EXPECT_EQ(Expected, Got); 2778 } 2779 2780 TEST(YAMLIO, TestEscaped) { 2781 // Single quote 2782 TestEscaped("@abc@", "'@abc@'"); 2783 // No quote 2784 TestEscaped("abc", "abc"); 2785 // Forward slash quoted 2786 TestEscaped("abc/", "'abc/'"); 2787 // Double quote non-printable 2788 TestEscaped("\01@abc@", "\"\\x01@abc@\""); 2789 // Double quote inside single quote 2790 TestEscaped("abc\"fdf", "'abc\"fdf'"); 2791 // Double quote inside double quote 2792 TestEscaped("\01bc\"fdf", "\"\\x01bc\\\"fdf\""); 2793 // Single quote inside single quote 2794 TestEscaped("abc'fdf", "'abc''fdf'"); 2795 // UTF8 2796 TestEscaped("/*параметр*/", "\"/*параметр*/\""); 2797 // UTF8 with single quote inside double quote 2798 TestEscaped("parameter 'параметр' is unused", 2799 "\"parameter 'параметр' is unused\""); 2800 2801 // String with embedded non-printable multibyte UTF-8 sequence (U+200B 2802 // zero-width space). The thing to test here is that we emit a 2803 // unicode-scalar level escape like \uNNNN (at the YAML level), and don't 2804 // just pass the UTF-8 byte sequence through as with quoted printables. 2805 { 2806 const unsigned char foobar[10] = {'f', 'o', 'o', 2807 0xE2, 0x80, 0x8B, // UTF-8 of U+200B 2808 'b', 'a', 'r', 2809 0x0}; 2810 TestEscaped((char const *)foobar, "\"foo\\u200Bbar\""); 2811 } 2812 } 2813 2814 TEST(YAMLIO, Numeric) { 2815 EXPECT_TRUE(isNumeric(".inf")); 2816 EXPECT_TRUE(isNumeric(".INF")); 2817 EXPECT_TRUE(isNumeric(".Inf")); 2818 EXPECT_TRUE(isNumeric("-.inf")); 2819 EXPECT_TRUE(isNumeric("+.inf")); 2820 2821 EXPECT_TRUE(isNumeric(".nan")); 2822 EXPECT_TRUE(isNumeric(".NaN")); 2823 EXPECT_TRUE(isNumeric(".NAN")); 2824 2825 EXPECT_TRUE(isNumeric("0")); 2826 EXPECT_TRUE(isNumeric("0.")); 2827 EXPECT_TRUE(isNumeric("0.0")); 2828 EXPECT_TRUE(isNumeric("-0.0")); 2829 EXPECT_TRUE(isNumeric("+0.0")); 2830 2831 EXPECT_TRUE(isNumeric("12345")); 2832 EXPECT_TRUE(isNumeric("012345")); 2833 EXPECT_TRUE(isNumeric("+12.0")); 2834 EXPECT_TRUE(isNumeric(".5")); 2835 EXPECT_TRUE(isNumeric("+.5")); 2836 EXPECT_TRUE(isNumeric("-1.0")); 2837 2838 EXPECT_TRUE(isNumeric("2.3e4")); 2839 EXPECT_TRUE(isNumeric("-2E+05")); 2840 EXPECT_TRUE(isNumeric("+12e03")); 2841 EXPECT_TRUE(isNumeric("6.8523015e+5")); 2842 2843 EXPECT_TRUE(isNumeric("1.e+1")); 2844 EXPECT_TRUE(isNumeric(".0e+1")); 2845 2846 EXPECT_TRUE(isNumeric("0x2aF3")); 2847 EXPECT_TRUE(isNumeric("0o01234567")); 2848 2849 EXPECT_FALSE(isNumeric("not a number")); 2850 EXPECT_FALSE(isNumeric(".")); 2851 EXPECT_FALSE(isNumeric(".e+1")); 2852 EXPECT_FALSE(isNumeric(".1e")); 2853 EXPECT_FALSE(isNumeric(".1e+")); 2854 EXPECT_FALSE(isNumeric(".1e++1")); 2855 2856 EXPECT_FALSE(isNumeric("ABCD")); 2857 EXPECT_FALSE(isNumeric("+0x2AF3")); 2858 EXPECT_FALSE(isNumeric("-0x2AF3")); 2859 EXPECT_FALSE(isNumeric("0x2AF3Z")); 2860 EXPECT_FALSE(isNumeric("0o012345678")); 2861 EXPECT_FALSE(isNumeric("0xZ")); 2862 EXPECT_FALSE(isNumeric("-0o012345678")); 2863 EXPECT_FALSE(isNumeric("000003A8229434B839616A25C16B0291F77A438B")); 2864 2865 EXPECT_FALSE(isNumeric("")); 2866 EXPECT_FALSE(isNumeric(".")); 2867 EXPECT_FALSE(isNumeric(".e+1")); 2868 EXPECT_FALSE(isNumeric(".e+")); 2869 EXPECT_FALSE(isNumeric(".e")); 2870 EXPECT_FALSE(isNumeric("e1")); 2871 2872 // Deprecated formats: as for YAML 1.2 specification, the following are not 2873 // valid numbers anymore: 2874 // 2875 // * Sexagecimal numbers 2876 // * Decimal numbers with comma s the delimiter 2877 // * "inf", "nan" without '.' prefix 2878 EXPECT_FALSE(isNumeric("3:25:45")); 2879 EXPECT_FALSE(isNumeric("+12,345")); 2880 EXPECT_FALSE(isNumeric("-inf")); 2881 EXPECT_FALSE(isNumeric("1,230.15")); 2882 } 2883 2884 //===----------------------------------------------------------------------===// 2885 // Test PolymorphicTraits and TaggedScalarTraits 2886 //===----------------------------------------------------------------------===// 2887 2888 struct Poly { 2889 enum NodeKind { 2890 NK_Scalar, 2891 NK_Seq, 2892 NK_Map, 2893 } Kind; 2894 2895 Poly(NodeKind Kind) : Kind(Kind) {} 2896 2897 virtual ~Poly() = default; 2898 2899 NodeKind getKind() const { return Kind; } 2900 }; 2901 2902 struct Scalar : Poly { 2903 enum ScalarKind { 2904 SK_Unknown, 2905 SK_Double, 2906 SK_Bool, 2907 } SKind; 2908 2909 union { 2910 double DoubleValue; 2911 bool BoolValue; 2912 }; 2913 2914 Scalar() : Poly(NK_Scalar), SKind(SK_Unknown) {} 2915 Scalar(double DoubleValue) 2916 : Poly(NK_Scalar), SKind(SK_Double), DoubleValue(DoubleValue) {} 2917 Scalar(bool BoolValue) 2918 : Poly(NK_Scalar), SKind(SK_Bool), BoolValue(BoolValue) {} 2919 2920 static bool classof(const Poly *N) { return N->getKind() == NK_Scalar; } 2921 }; 2922 2923 struct Seq : Poly, std::vector<std::unique_ptr<Poly>> { 2924 Seq() : Poly(NK_Seq) {} 2925 2926 static bool classof(const Poly *N) { return N->getKind() == NK_Seq; } 2927 }; 2928 2929 struct Map : Poly, llvm::StringMap<std::unique_ptr<Poly>> { 2930 Map() : Poly(NK_Map) {} 2931 2932 static bool classof(const Poly *N) { return N->getKind() == NK_Map; } 2933 }; 2934 2935 namespace llvm { 2936 namespace yaml { 2937 2938 template <> struct PolymorphicTraits<std::unique_ptr<Poly>> { 2939 static NodeKind getKind(const std::unique_ptr<Poly> &N) { 2940 if (isa<Scalar>(*N)) 2941 return NodeKind::Scalar; 2942 if (isa<Seq>(*N)) 2943 return NodeKind::Sequence; 2944 if (isa<Map>(*N)) 2945 return NodeKind::Map; 2946 llvm_unreachable("unsupported node type"); 2947 } 2948 2949 static Scalar &getAsScalar(std::unique_ptr<Poly> &N) { 2950 if (!N || !isa<Scalar>(*N)) 2951 N = std::make_unique<Scalar>(); 2952 return *cast<Scalar>(N.get()); 2953 } 2954 2955 static Seq &getAsSequence(std::unique_ptr<Poly> &N) { 2956 if (!N || !isa<Seq>(*N)) 2957 N = std::make_unique<Seq>(); 2958 return *cast<Seq>(N.get()); 2959 } 2960 2961 static Map &getAsMap(std::unique_ptr<Poly> &N) { 2962 if (!N || !isa<Map>(*N)) 2963 N = std::make_unique<Map>(); 2964 return *cast<Map>(N.get()); 2965 } 2966 }; 2967 2968 template <> struct TaggedScalarTraits<Scalar> { 2969 static void output(const Scalar &S, void *Ctxt, raw_ostream &ScalarOS, 2970 raw_ostream &TagOS) { 2971 switch (S.SKind) { 2972 case Scalar::SK_Unknown: 2973 report_fatal_error("output unknown scalar"); 2974 break; 2975 case Scalar::SK_Double: 2976 TagOS << "!double"; 2977 ScalarTraits<double>::output(S.DoubleValue, Ctxt, ScalarOS); 2978 break; 2979 case Scalar::SK_Bool: 2980 TagOS << "!bool"; 2981 ScalarTraits<bool>::output(S.BoolValue, Ctxt, ScalarOS); 2982 break; 2983 } 2984 } 2985 2986 static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt, 2987 Scalar &S) { 2988 S.SKind = StringSwitch<Scalar::ScalarKind>(Tag) 2989 .Case("!double", Scalar::SK_Double) 2990 .Case("!bool", Scalar::SK_Bool) 2991 .Default(Scalar::SK_Unknown); 2992 switch (S.SKind) { 2993 case Scalar::SK_Unknown: 2994 return StringRef("unknown scalar tag"); 2995 case Scalar::SK_Double: 2996 return ScalarTraits<double>::input(ScalarStr, Ctxt, S.DoubleValue); 2997 case Scalar::SK_Bool: 2998 return ScalarTraits<bool>::input(ScalarStr, Ctxt, S.BoolValue); 2999 } 3000 llvm_unreachable("unknown scalar kind"); 3001 } 3002 3003 static QuotingType mustQuote(const Scalar &S, StringRef Str) { 3004 switch (S.SKind) { 3005 case Scalar::SK_Unknown: 3006 report_fatal_error("quote unknown scalar"); 3007 case Scalar::SK_Double: 3008 return ScalarTraits<double>::mustQuote(Str); 3009 case Scalar::SK_Bool: 3010 return ScalarTraits<bool>::mustQuote(Str); 3011 } 3012 llvm_unreachable("unknown scalar kind"); 3013 } 3014 }; 3015 3016 template <> struct CustomMappingTraits<Map> { 3017 static void inputOne(IO &IO, StringRef Key, Map &M) { 3018 IO.mapRequired(Key.str().c_str(), M[Key]); 3019 } 3020 3021 static void output(IO &IO, Map &M) { 3022 for (auto &N : M) 3023 IO.mapRequired(N.getKey().str().c_str(), N.getValue()); 3024 } 3025 }; 3026 3027 template <> struct SequenceTraits<Seq> { 3028 static size_t size(IO &IO, Seq &A) { return A.size(); } 3029 3030 static std::unique_ptr<Poly> &element(IO &IO, Seq &A, size_t Index) { 3031 if (Index >= A.size()) 3032 A.resize(Index + 1); 3033 return A[Index]; 3034 } 3035 }; 3036 3037 } // namespace yaml 3038 } // namespace llvm 3039 3040 TEST(YAMLIO, TestReadWritePolymorphicScalar) { 3041 std::string intermediate; 3042 std::unique_ptr<Poly> node = std::make_unique<Scalar>(true); 3043 3044 llvm::raw_string_ostream ostr(intermediate); 3045 Output yout(ostr); 3046 #ifdef GTEST_HAS_DEATH_TEST 3047 #ifndef NDEBUG 3048 EXPECT_DEATH(yout << node, "plain scalar documents are not supported"); 3049 #endif 3050 #endif 3051 } 3052 3053 TEST(YAMLIO, TestReadWritePolymorphicSeq) { 3054 std::string intermediate; 3055 { 3056 auto seq = std::make_unique<Seq>(); 3057 seq->push_back(std::make_unique<Scalar>(true)); 3058 seq->push_back(std::make_unique<Scalar>(1.0)); 3059 auto node = llvm::unique_dyn_cast<Poly>(seq); 3060 3061 llvm::raw_string_ostream ostr(intermediate); 3062 Output yout(ostr); 3063 yout << node; 3064 } 3065 { 3066 Input yin(intermediate); 3067 std::unique_ptr<Poly> node; 3068 yin >> node; 3069 3070 EXPECT_FALSE(yin.error()); 3071 auto seq = llvm::dyn_cast<Seq>(node.get()); 3072 ASSERT_TRUE(seq); 3073 ASSERT_EQ(seq->size(), 2u); 3074 auto first = llvm::dyn_cast<Scalar>((*seq)[0].get()); 3075 ASSERT_TRUE(first); 3076 EXPECT_EQ(first->SKind, Scalar::SK_Bool); 3077 EXPECT_TRUE(first->BoolValue); 3078 auto second = llvm::dyn_cast<Scalar>((*seq)[1].get()); 3079 ASSERT_TRUE(second); 3080 EXPECT_EQ(second->SKind, Scalar::SK_Double); 3081 EXPECT_EQ(second->DoubleValue, 1.0); 3082 } 3083 } 3084 3085 TEST(YAMLIO, TestReadWritePolymorphicMap) { 3086 std::string intermediate; 3087 { 3088 auto map = std::make_unique<Map>(); 3089 (*map)["foo"] = std::make_unique<Scalar>(false); 3090 (*map)["bar"] = std::make_unique<Scalar>(2.0); 3091 std::unique_ptr<Poly> node = llvm::unique_dyn_cast<Poly>(map); 3092 3093 llvm::raw_string_ostream ostr(intermediate); 3094 Output yout(ostr); 3095 yout << node; 3096 } 3097 { 3098 Input yin(intermediate); 3099 std::unique_ptr<Poly> node; 3100 yin >> node; 3101 3102 EXPECT_FALSE(yin.error()); 3103 auto map = llvm::dyn_cast<Map>(node.get()); 3104 ASSERT_TRUE(map); 3105 auto foo = llvm::dyn_cast<Scalar>((*map)["foo"].get()); 3106 ASSERT_TRUE(foo); 3107 EXPECT_EQ(foo->SKind, Scalar::SK_Bool); 3108 EXPECT_FALSE(foo->BoolValue); 3109 auto bar = llvm::dyn_cast<Scalar>((*map)["bar"].get()); 3110 ASSERT_TRUE(bar); 3111 EXPECT_EQ(bar->SKind, Scalar::SK_Double); 3112 EXPECT_EQ(bar->DoubleValue, 2.0); 3113 } 3114 } 3115 3116 TEST(YAMLIO, TestAnchorMapError) { 3117 Input yin("& & &: "); 3118 yin.setCurrentDocument(); 3119 EXPECT_TRUE(yin.error()); 3120 } 3121 3122 TEST(YAMLIO, TestFlowSequenceTokenErrors) { 3123 Input yin(","); 3124 EXPECT_FALSE(yin.setCurrentDocument()); 3125 EXPECT_TRUE(yin.error()); 3126 3127 Input yin2("]"); 3128 EXPECT_FALSE(yin2.setCurrentDocument()); 3129 EXPECT_TRUE(yin2.error()); 3130 3131 Input yin3("}"); 3132 EXPECT_FALSE(yin3.setCurrentDocument()); 3133 EXPECT_TRUE(yin3.error()); 3134 } 3135 3136 TEST(YAMLIO, TestDirectiveMappingNoValue) { 3137 Input yin("%YAML\n{5:"); 3138 EXPECT_FALSE(yin.setCurrentDocument()); 3139 EXPECT_TRUE(yin.error()); 3140 3141 Input yin2("%TAG\n'\x98!< :\n"); 3142 yin2.setCurrentDocument(); 3143 EXPECT_TRUE(yin2.error()); 3144 } 3145 3146 TEST(YAMLIO, TestUnescapeInfiniteLoop) { 3147 Input yin("\"\\u\\^#\\\\\""); 3148 yin.setCurrentDocument(); 3149 EXPECT_TRUE(yin.error()); 3150 } 3151 3152 TEST(YAMLIO, TestScannerUnexpectedCharacter) { 3153 Input yin("!<$\x9F."); 3154 EXPECT_FALSE(yin.setCurrentDocument()); 3155 EXPECT_TRUE(yin.error()); 3156 } 3157 3158 TEST(YAMLIO, TestUnknownDirective) { 3159 Input yin("%"); 3160 EXPECT_FALSE(yin.setCurrentDocument()); 3161 EXPECT_TRUE(yin.error()); 3162 3163 Input yin2("%)"); 3164 EXPECT_FALSE(yin2.setCurrentDocument()); 3165 EXPECT_TRUE(yin2.error()); 3166 } 3167 3168 TEST(YAMLIO, TestEmptyAlias) { 3169 Input yin("&"); 3170 EXPECT_FALSE(yin.setCurrentDocument()); 3171 EXPECT_TRUE(yin.error()); 3172 } 3173 3174 TEST(YAMLIO, TestEmptyAnchor) { 3175 Input yin("*"); 3176 EXPECT_FALSE(yin.setCurrentDocument()); 3177 } 3178 3179 TEST(YAMLIO, TestScannerNoNullEmpty) { 3180 std::vector<char> str{}; 3181 Input yin(llvm::StringRef(str.data(), str.size())); 3182 yin.setCurrentDocument(); 3183 EXPECT_FALSE(yin.error()); 3184 } 3185 3186 TEST(YAMLIO, TestScannerNoNullSequenceOfNull) { 3187 std::vector<char> str{'-'}; 3188 Input yin(llvm::StringRef(str.data(), str.size())); 3189 yin.setCurrentDocument(); 3190 EXPECT_FALSE(yin.error()); 3191 } 3192 3193 TEST(YAMLIO, TestScannerNoNullSimpleSequence) { 3194 std::vector<char> str{'-', ' ', 'a'}; 3195 Input yin(llvm::StringRef(str.data(), str.size())); 3196 yin.setCurrentDocument(); 3197 EXPECT_FALSE(yin.error()); 3198 } 3199 3200 TEST(YAMLIO, TestScannerNoNullUnbalancedMap) { 3201 std::vector<char> str{'{'}; 3202 Input yin(llvm::StringRef(str.data(), str.size())); 3203 yin.setCurrentDocument(); 3204 EXPECT_TRUE(yin.error()); 3205 } 3206 3207 TEST(YAMLIO, TestScannerNoNullEmptyMap) { 3208 std::vector<char> str{'{', '}'}; 3209 Input yin(llvm::StringRef(str.data(), str.size())); 3210 yin.setCurrentDocument(); 3211 EXPECT_FALSE(yin.error()); 3212 } 3213 3214 TEST(YAMLIO, TestScannerNoNullUnbalancedSequence) { 3215 std::vector<char> str{'['}; 3216 Input yin(llvm::StringRef(str.data(), str.size())); 3217 yin.setCurrentDocument(); 3218 EXPECT_TRUE(yin.error()); 3219 } 3220 3221 TEST(YAMLIO, TestScannerNoNullEmptySequence) { 3222 std::vector<char> str{'[', ']'}; 3223 Input yin(llvm::StringRef(str.data(), str.size())); 3224 yin.setCurrentDocument(); 3225 EXPECT_FALSE(yin.error()); 3226 } 3227 3228 TEST(YAMLIO, TestScannerNoNullScalarUnbalancedDoubleQuote) { 3229 std::vector<char> str{'"'}; 3230 Input yin(llvm::StringRef(str.data(), str.size())); 3231 yin.setCurrentDocument(); 3232 EXPECT_TRUE(yin.error()); 3233 } 3234 3235 TEST(YAMLIO, TestScannerNoNullScalarUnbalancedSingleQuote) { 3236 std::vector<char> str{'\''}; 3237 Input yin(llvm::StringRef(str.data(), str.size())); 3238 yin.setCurrentDocument(); 3239 EXPECT_TRUE(yin.error()); 3240 } 3241 3242 TEST(YAMLIO, TestScannerNoNullEmptyAlias) { 3243 std::vector<char> str{'&'}; 3244 Input yin(llvm::StringRef(str.data(), str.size())); 3245 yin.setCurrentDocument(); 3246 EXPECT_TRUE(yin.error()); 3247 } 3248 3249 TEST(YAMLIO, TestScannerNoNullEmptyAnchor) { 3250 std::vector<char> str{'*'}; 3251 Input yin(llvm::StringRef(str.data(), str.size())); 3252 yin.setCurrentDocument(); 3253 EXPECT_TRUE(yin.error()); 3254 } 3255 3256 TEST(YAMLIO, TestScannerNoNullDecodeInvalidUTF8) { 3257 std::vector<char> str{'\xef'}; 3258 Input yin(llvm::StringRef(str.data(), str.size())); 3259 yin.setCurrentDocument(); 3260 EXPECT_TRUE(yin.error()); 3261 } 3262 3263 TEST(YAMLIO, TestScannerNoNullScanPlainScalarInFlow) { 3264 std::vector<char> str{'{', 'a', ':'}; 3265 Input yin(llvm::StringRef(str.data(), str.size())); 3266 yin.setCurrentDocument(); 3267 EXPECT_TRUE(yin.error()); 3268 } 3269