[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / Support / YAMLIOTest.cpp
blobae676c73970e8e4185d0fe8b2365cdbd0eab8341
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 //===----------------------------------------------------------------------===//
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"
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;
37 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
42 //===----------------------------------------------------------------------===//
43 // Test MappingTraits
44 //===----------------------------------------------------------------------===//
46 struct FooBar {
47 int foo;
48 int bar;
50 typedef std::vector<FooBar> FooBarSequence;
52 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
54 struct FooBarContainer {
55 FooBarSequence fbs;
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);
68 template <> struct MappingTraits<FooBarContainer> {
69 static void mapping(IO &io, FooBarContainer &fb) {
70 io.mapRequired("fbs", fb.fbs);
78 // Test the reading of a yaml mapping
80 TEST(YAMLIO, TestMapRead) {
81 FooBar doc;
83 Input yin("---\nfoo: 3\nbar: 5\n...\n");
84 yin >> doc;
86 EXPECT_FALSE(yin.error());
87 EXPECT_EQ(doc.foo, 3);
88 EXPECT_EQ(doc.bar, 5);
92 Input yin("{foo: 3, bar: 5}");
93 yin >> doc;
95 EXPECT_FALSE(yin.error());
96 EXPECT_EQ(doc.foo, 3);
97 EXPECT_EQ(doc.bar, 5);
101 TEST(YAMLIO, TestMalformedMapRead) {
102 FooBar doc;
103 Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages);
104 yin >> doc;
105 EXPECT_TRUE(!!yin.error());
109 // Test the reading of a yaml sequence of mappings
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;
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);
127 // Test the reading of a map containing a yaml sequence of mappings
129 TEST(YAMLIO, TestContainerSequenceMapRead) {
131 FooBarContainer cont;
132 Input yin2("---\nfbs:\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n");
133 yin2 >> cont;
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);
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);
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);
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);
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);
181 // Test the reading of a map containing a malformed yaml sequence
183 TEST(YAMLIO, TestMalformedContainerSequenceMapRead) {
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);
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);
205 // Test writing then reading back a sequence of mappings
207 TEST(YAMLIO, TestSequenceMapWriteAndRead) {
208 std::string intermediate;
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);
220 llvm::raw_string_ostream ostr(intermediate);
221 Output yout(ostr);
222 yout << seq;
226 Input yin(intermediate);
227 FooBarSequence seq2;
228 yin >> seq2;
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);
242 // Test reading the entire struct as an enum.
245 struct FooBarEnum {
246 int Foo;
247 int Bar;
248 bool operator==(const FooBarEnum &R) const {
249 return Foo == R.Foo && Bar == R.Bar;
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}));
260 static void mapping(IO &io, FooBarEnum &Val) {
261 io.mapOptional("Foo", Val.Foo);
262 io.mapOptional("Bar", Val.Bar);
265 } // namespace yaml
266 } // namespace llvm
268 TEST(YAMLIO, TestMapEnumRead) {
269 FooBarEnum Doc;
271 Input Yin("OnlyFoo");
272 Yin >> Doc;
273 EXPECT_FALSE(Yin.error());
274 EXPECT_EQ(Doc.Foo, 1);
275 EXPECT_EQ(Doc.Bar, 0);
278 Input Yin("OnlyBar");
279 Yin >> Doc;
280 EXPECT_FALSE(Yin.error());
281 EXPECT_EQ(Doc.Foo, 0);
282 EXPECT_EQ(Doc.Bar, 1);
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);
294 // Test YAML filename handling.
296 static void testErrorFilename(const llvm::SMDiagnostic &Error, void *) {
297 EXPECT_EQ(Error.getFilename(), "foo.yaml");
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;
306 EXPECT_TRUE(!!yin.error());
309 struct WithStringField {
310 std::string str1;
311 std::string str2;
312 std::string str3;
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);
324 } // namespace yaml
325 } // namespace llvm
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";
333 std::string Serialized;
335 llvm::raw_string_ostream OS(Serialized);
336 Output YOut(OS);
337 YOut << Original;
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);
346 // Also check it parses back without the errors.
347 WithStringField Deserialized;
349 Input YIn(Serialized);
350 YIn >> Deserialized;
351 ASSERT_FALSE(YIn.error())
352 << "Parsing error occurred during deserialization. Serialized string:\n"
353 << Serialized;
355 EXPECT_EQ(Original.str1, Deserialized.str1);
356 EXPECT_EQ(Original.str2, Deserialized.str2);
357 EXPECT_EQ(Original.str3, Deserialized.str3);
360 TEST(YAMLIO, NoQuotesForTab) {
361 WithStringField WithTab;
362 WithTab.str1 = "aba\tcaba";
363 std::string Serialized;
365 llvm::raw_string_ostream OS(Serialized);
366 Output YOut(OS);
367 YOut << WithTab;
369 auto ExpectedPrefix = "---\n"
370 "str1: aba\tcaba\n";
371 EXPECT_THAT(Serialized, StartsWith(ExpectedPrefix));
374 //===----------------------------------------------------------------------===//
375 // Test built-in types
376 //===----------------------------------------------------------------------===//
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;
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);
427 // Test the reading of all built-in scalar conversions
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;
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));
474 // Test writing then reading back all built-in scalar types
476 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
477 std::string intermediate;
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;
498 llvm::raw_string_ostream ostr(intermediate);
499 Output yout(ostr);
500 yout << map;
504 Input yin(intermediate);
505 BuiltInTypes map;
506 yin >> map;
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));
529 //===----------------------------------------------------------------------===//
530 // Test endian-aware types
531 //===----------------------------------------------------------------------===//
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;
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;
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);
569 // Test the reading of all endian scalar conversions
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;
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);
597 // Test writing then reading back all endian-aware scalar types
599 TEST(YAMLIO, TestReadWriteEndianTypes) {
600 std::string intermediate;
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;
612 llvm::raw_string_ostream ostr(intermediate);
613 Output yout(ostr);
614 yout << map;
618 Input yin(intermediate);
619 EndianTypes map;
620 yin >> map;
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);
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),
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;
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);
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);
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);
671 } // namespace yaml
672 } // namespace llvm
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;
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);
691 TEST(YAMLIO, TestReadWriteEndianEnums) {
692 std::string intermediate;
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;
700 llvm::raw_string_ostream ostr(intermediate);
701 Output yout(ostr);
702 yout << map;
706 Input yin(intermediate);
707 EndianEnums map;
708 yin >> map;
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);
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;
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);
779 TEST(YAMLIO, TestReadWriteStringTypes) {
780 std::string intermediate;
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);
808 llvm::raw_string_ostream ostr(intermediate);
809 Output yout(ostr);
810 yout << map;
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\""));
835 Input yin(intermediate);
836 StringTypes map;
837 yin >> map;
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);
856 //===----------------------------------------------------------------------===//
857 // Test ScalarEnumerationTraits
858 //===----------------------------------------------------------------------===//
860 enum Colors {
861 cRed,
862 cBlue,
863 cGreen,
864 cYellow
867 struct ColorMap {
868 Colors c1;
869 Colors c2;
870 Colors c3;
871 Colors c4;
872 Colors c5;
873 Colors c6;
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);
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
903 // Test reading enumerated scalars
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;
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
926 //===----------------------------------------------------------------------===//
927 // Test ScalarBitSetTraits
928 //===----------------------------------------------------------------------===//
930 enum MyFlags {
931 flagNone = 0,
932 flagBig = 1 << 0,
933 flagFlat = 1 << 1,
934 flagRound = 1 << 2,
935 flagPointy = 1 << 3
937 inline MyFlags operator|(MyFlags a, MyFlags b) {
938 return static_cast<MyFlags>(
939 static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
942 struct FlagsMap {
943 MyFlags f1;
944 MyFlags f2;
945 MyFlags f3;
946 MyFlags f4;
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);
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);
975 // Test reading flow sequence representing bit-mask values
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;
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
995 // Test writing then reading back bit-mask values
997 TEST(YAMLIO, TestReadWriteFlags) {
998 std::string intermediate;
1000 FlagsMap map;
1001 map.f1 = flagBig;
1002 map.f2 = flagRound | flagFlat;
1003 map.f3 = flagNone;
1004 map.f4 = flagNone;
1006 llvm::raw_string_ostream ostr(intermediate);
1007 Output yout(ostr);
1008 yout << map;
1012 Input yin(intermediate);
1013 FlagsMap map2;
1014 yin >> map2;
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
1026 //===----------------------------------------------------------------------===//
1027 // Test ScalarTraits
1028 //===----------------------------------------------------------------------===//
1030 struct MyCustomType {
1031 int length;
1032 int width;
1035 struct MyCustomTypeMap {
1036 MyCustomType f1;
1037 MyCustomType f2;
1038 int f3;
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);
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);
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";
1067 StringRef widthStr = scalar.drop_front(byStart+2);
1068 widthStr = widthStr.ltrim();
1069 if ( widthStr.getAsInteger(0, value.width) ) {
1070 return "malformed width";
1072 return StringRef();
1074 else {
1075 return "malformed by";
1078 static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
1085 // Test writing then reading back custom values
1087 TEST(YAMLIO, TestReadWriteMyCustomType) {
1088 std::string intermediate;
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;
1097 llvm::raw_string_ostream ostr(intermediate);
1098 Output yout(ostr);
1099 yout << map;
1103 Input yin(intermediate);
1104 MyCustomTypeMap map2;
1105 yin >> map2;
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);
1117 //===----------------------------------------------------------------------===//
1118 // Test BlockScalarTraits
1119 //===----------------------------------------------------------------------===//
1121 struct MultilineStringType {
1122 std::string str;
1125 struct MultilineStringTypeMap {
1126 MultilineStringType name;
1127 MultilineStringType description;
1128 MultilineStringType ingredients;
1129 MultilineStringType recipes;
1130 MultilineStringType warningLabels;
1131 MultilineStringType documentation;
1132 int price;
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);
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;
1161 static StringRef input(StringRef scalar, void *ctxt,
1162 MultilineStringType &value) {
1163 value.str = scalar.str();
1164 return StringRef();
1170 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
1173 // Test writing then reading back custom values
1175 TEST(YAMLIO, TestReadWriteMultilineStringType) {
1176 std::string intermediate;
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;
1187 llvm::raw_string_ostream ostr(intermediate);
1188 Output yout(ostr);
1189 yout << map;
1192 Input yin(intermediate);
1193 MultilineStringTypeMap map2;
1194 yin >> map2;
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);
1208 // Test writing then reading back custom values
1210 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
1211 std::string intermediate;
1213 std::vector<MultilineStringType> documents;
1214 MultilineStringType doc;
1215 doc.str = "Hello\nWorld";
1216 documents.push_back(doc);
1218 llvm::raw_string_ostream ostr(intermediate);
1219 Output yout(ostr);
1220 yout << documents;
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("--- |"));
1227 Input yin(intermediate);
1228 std::vector<MultilineStringType> documents2;
1229 yin >> documents2;
1231 EXPECT_FALSE(yin.error());
1232 EXPECT_EQ(documents2.size(), size_t(1));
1233 EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
1237 TEST(YAMLIO, TestReadWriteBlockScalarValue) {
1238 std::string intermediate;
1240 MultilineStringType doc;
1241 doc.str = "Just a block\nscalar doc";
1243 llvm::raw_string_ostream ostr(intermediate);
1244 Output yout(ostr);
1245 yout << doc;
1248 Input yin(intermediate);
1249 MultilineStringType doc;
1250 yin >> doc;
1252 EXPECT_FALSE(yin.error());
1253 EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
1257 //===----------------------------------------------------------------------===//
1258 // Test flow sequences
1259 //===----------------------------------------------------------------------===//
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)
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;
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();
1282 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
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);
1290 static StringRef input(StringRef S, void *Ctx, MyString &V) {
1291 return Impl::input(S, Ctx, V.value);
1293 static QuotingType mustQuote(StringRef S) {
1294 return Impl::mustQuote(S);
1300 struct NameAndNumbers {
1301 llvm::StringRef name;
1302 std::vector<MyString> strings;
1303 std::vector<MyNumber> single;
1304 std::vector<MyNumber> numbers;
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);
1321 typedef std::vector<MyNumber> MyNumberFlowSequence;
1323 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
1325 struct NameAndNumbersFlow {
1326 llvm::StringRef name;
1327 std::vector<MyNumberFlowSequence> sequenceOfNumbers;
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);
1343 // Test writing then reading back custom values
1345 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
1346 std::string intermediate;
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);
1357 llvm::raw_string_ostream ostr(intermediate);
1358 Output yout(ostr);
1359 yout << map;
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"));
1369 Input yin(intermediate);
1370 NameAndNumbers map2;
1371 yin >> map2;
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]);
1389 // Test writing then reading back a sequence of flow sequences.
1391 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
1392 std::string intermediate;
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());
1402 llvm::raw_string_ostream ostr(intermediate);
1403 Output yout(ostr);
1404 yout << map;
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("- [ ]"));
1416 Input yin(intermediate);
1417 NameAndNumbersFlow map2;
1418 yin >> map2;
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());
1433 //===----------------------------------------------------------------------===//
1434 // Test normalizing/denormalizing
1435 //===----------------------------------------------------------------------===//
1437 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
1439 typedef std::vector<TotalSeconds> SecondsSequence;
1441 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
1444 namespace llvm {
1445 namespace yaml {
1446 template <>
1447 struct MappingTraits<TotalSeconds> {
1449 class NormalizedSeconds {
1450 public:
1451 NormalizedSeconds(IO &io)
1452 : hours(0), minutes(0), seconds(0) {
1454 NormalizedSeconds(IO &, TotalSeconds &secs)
1455 : hours(secs/3600),
1456 minutes((secs - (hours*3600))/60),
1457 seconds(secs % 60) {
1459 TotalSeconds denormalize(IO &) {
1460 return TotalSeconds(hours*3600 + minutes*60 + seconds);
1463 uint32_t hours;
1464 uint8_t minutes;
1465 uint8_t seconds;
1468 static void mapping(IO &io, TotalSeconds &secs) {
1469 MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
1471 io.mapOptional("hours", keys->hours, 0);
1472 io.mapOptional("minutes", keys->minutes, 0);
1473 io.mapRequired("seconds", keys->seconds);
1481 // Test the reading of a yaml sequence of mappings
1483 TEST(YAMLIO, TestReadMySecondsSequence) {
1484 SecondsSequence seq;
1485 Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n");
1486 yin >> seq;
1488 EXPECT_FALSE(yin.error());
1489 EXPECT_EQ(seq.size(), 2UL);
1490 EXPECT_EQ(seq[0], 3605U);
1491 EXPECT_EQ(seq[1], 59U);
1496 // Test writing then reading back custom values
1498 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
1499 std::string intermediate;
1501 SecondsSequence seq;
1502 seq.push_back(4000);
1503 seq.push_back(500);
1504 seq.push_back(59);
1506 llvm::raw_string_ostream ostr(intermediate);
1507 Output yout(ostr);
1508 yout << seq;
1511 Input yin(intermediate);
1512 SecondsSequence seq2;
1513 yin >> seq2;
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);
1524 //===----------------------------------------------------------------------===//
1525 // Test dynamic typing
1526 //===----------------------------------------------------------------------===//
1528 enum AFlags {
1534 enum BFlags {
1540 enum Kind {
1541 kindA,
1542 kindB
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;
1552 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
1554 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
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);
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);
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);
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;
1603 // Test the reading of a yaml sequence dynamic types
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;
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);
1619 // Test writing then reading back dynamic types
1621 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
1622 std::string intermediate;
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));
1631 llvm::raw_string_ostream ostr(intermediate);
1632 Output yout(ostr);
1633 yout << seq;
1636 Input yin(intermediate);
1637 KindAndFlagsSequence seq2;
1638 yin >> seq2;
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);
1656 //===----------------------------------------------------------------------===//
1657 // Test document list
1658 //===----------------------------------------------------------------------===//
1660 struct FooBarMap {
1661 int foo;
1662 int bar;
1664 typedef std::vector<FooBarMap> FooBarMapDocumentList;
1666 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
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);
1683 // Test the reading of a yaml mapping
1685 TEST(YAMLIO, TestDocRead) {
1686 FooBarMap doc;
1687 Input yin("---\nfoo: 3\nbar: 5\n...\n");
1688 yin >> doc;
1690 EXPECT_FALSE(yin.error());
1691 EXPECT_EQ(doc.foo, 3);
1692 EXPECT_EQ(doc.bar,5);
1698 // Test writing then reading back a sequence of mappings
1700 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
1701 std::string intermediate;
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);
1713 llvm::raw_string_ostream ostr(intermediate);
1714 Output yout(ostr);
1715 yout << docList;
1720 Input yin(intermediate);
1721 std::vector<FooBarMap> docList2;
1722 yin >> docList2;
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);
1735 //===----------------------------------------------------------------------===//
1736 // Test document tags
1737 //===----------------------------------------------------------------------===//
1739 struct MyDouble {
1740 MyDouble() : value(0.0) { }
1741 MyDouble(double x) : value(x) { }
1742 double value;
1745 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
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);
1759 static void mappingDecimal(IO &io, MyDouble &d) {
1760 io.mapRequired("value", d.value);
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;
1775 // Test the reading of two different tagged yaml documents.
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);
1791 // Test writing then reading back tagged documents
1793 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1794 std::string intermediate;
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);
1802 llvm::raw_string_ostream ostr(intermediate);
1803 Output yout(ostr);
1804 yout << docList;
1808 Input yin(intermediate);
1809 std::vector<MyDouble> docList2;
1810 yin >> docList2;
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);
1820 //===----------------------------------------------------------------------===//
1821 // Test mapping validation
1822 //===----------------------------------------------------------------------===//
1824 struct MyValidation {
1825 double value;
1828 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
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);
1837 static std::string validate(IO &io, MyValidation &d) {
1838 if (d.value < 0)
1839 return "negative value";
1840 return {};
1848 // Test that validate() is called and complains about the negative value.
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());
1859 //===----------------------------------------------------------------------===//
1860 // Test flow mapping
1861 //===----------------------------------------------------------------------===//
1863 struct FlowFooBar {
1864 int foo;
1865 int bar;
1867 FlowFooBar() : foo(0), bar(0) {}
1868 FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
1871 typedef std::vector<FlowFooBar> FlowFooBarSequence;
1873 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
1875 struct FlowFooBarDoc {
1876 FlowFooBar attribute;
1877 FlowFooBarSequence seq;
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);
1889 static const bool flow = true;
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);
1903 // Test writing then reading back custom mappings
1905 TEST(YAMLIO, TestReadWriteMyFlowMapping) {
1906 std::string intermediate;
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));
1914 llvm::raw_string_ostream ostr(intermediate);
1915 Output yout(ostr);
1916 yout << doc;
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 }"));
1928 Input yin(intermediate);
1929 FlowFooBarDoc doc2;
1930 yin >> doc2;
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);
1945 //===----------------------------------------------------------------------===//
1946 // Test error handling
1947 //===----------------------------------------------------------------------===//
1950 // Test error handling of unknown enumerated scalar
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());
1967 // Test error handling of flow sequence with unknown value
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;
1980 EXPECT_TRUE(!!yin.error());
1985 // Test error handling reading built-in uint8_t type
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;
1998 EXPECT_TRUE(!!yin.error());
2003 // Test error handling reading built-in uint16_t type
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;
2016 EXPECT_TRUE(!!yin.error());
2021 // Test error handling reading built-in uint32_t type
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;
2034 EXPECT_TRUE(!!yin.error());
2039 // Test error handling reading built-in uint64_t type
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;
2052 EXPECT_TRUE(!!yin.error());
2057 // Test error handling reading built-in int8_t type
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;
2071 EXPECT_TRUE(!!yin.error());
2075 // Test error handling reading built-in int8_t type
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;
2089 EXPECT_TRUE(!!yin.error());
2094 // Test error handling reading built-in int16_t type
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;
2108 EXPECT_TRUE(!!yin.error());
2113 // Test error handling reading built-in int16_t type
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;
2127 EXPECT_TRUE(!!yin.error());
2132 // Test error handling reading built-in int32_t type
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;
2146 EXPECT_TRUE(!!yin.error());
2150 // Test error handling reading built-in int32_t type
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;
2164 EXPECT_TRUE(!!yin.error());
2169 // Test error handling reading built-in int64_t type
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;
2183 EXPECT_TRUE(!!yin.error());
2187 // Test error handling reading built-in int64_t type
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;
2201 EXPECT_TRUE(!!yin.error());
2205 // Test error handling reading built-in float type
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;
2219 EXPECT_TRUE(!!yin.error());
2223 // Test error handling reading built-in float type
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;
2237 EXPECT_TRUE(!!yin.error());
2241 // Test error handling reading built-in Hex8 type
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());
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());
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]);
2271 // Test error handling reading built-in Hex16 type
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());
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());
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]);
2300 // Test error handling reading built-in Hex32 type
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;
2313 EXPECT_TRUE(!!yin.error());
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());
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]);
2330 // Test error handling reading built-in Hex64 type
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());
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());
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]);
2358 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
2359 FooBar doc;
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());
2369 Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
2370 yin >> doc;
2371 EXPECT_TRUE(!!yin.error());
2375 struct OptionalTest {
2376 std::vector<int> Numbers;
2379 struct OptionalTestSeq {
2380 std::vector<OptionalTest> Tests;
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);
2393 template <>
2394 struct MappingTraits<OptionalTestSeq> {
2395 static void mapping(IO &IO, OptionalTestSeq &OTS) {
2396 IO.mapOptional("Tests", OTS.Tests);
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);
2414 std::string intermediate;
2416 llvm::raw_string_ostream ostr(intermediate);
2417 Output yout(ostr);
2418 yout << Seq;
2421 Input yin(intermediate);
2422 OptionalTestSeq Seq2;
2423 yin >> Seq2;
2425 EXPECT_FALSE(yin.error());
2427 EXPECT_EQ(4UL, Seq2.Tests.size());
2429 EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
2430 EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
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]);
2436 EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
2439 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
2440 FooBar doc;
2441 Input yin("");
2442 yin >> doc;
2443 EXPECT_TRUE(!!yin.error());
2446 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
2447 OptionalTest doc;
2448 Input yin("");
2449 yin >> doc;
2450 EXPECT_FALSE(yin.error());
2453 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
2454 std::vector<uint8_t> seq;
2455 Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
2456 yin >> seq;
2458 EXPECT_FALSE(yin.error());
2459 EXPECT_TRUE(seq.empty());
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) {}
2468 struct FlowSeq {
2469 llvm::StringRef str;
2470 FlowSeq(llvm::StringRef S) : str(S) {}
2471 FlowSeq() = default;
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);
2484 static const bool flow = true;
2487 template <>
2488 struct ScalarTraits<FlowSeq> {
2489 static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
2490 out << value.str;
2492 static StringRef input(StringRef scalar, void*, FlowSeq &value) {
2493 value.str = scalar;
2494 return "";
2497 static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
2502 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
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");
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);
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();
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();
2539 // 25 will allow the second field to be output on the first line.
2540 Output yout(ostr, nullptr, 25);
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();
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();
2561 // 0 means no wrapping.
2562 Output yout(ostr, nullptr, 0);
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();
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();
2582 struct MappingContext {
2583 int A = 0;
2585 struct SimpleMap {
2586 int B = 0;
2587 int C = 0;
2590 struct NestedMap {
2591 NestedMap(MappingContext &Context) : Context(Context) {}
2592 SimpleMap Simple;
2593 MappingContext &Context;
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);
2607 template <> struct MappingTraits<NestedMap> {
2608 static void mapping(IO &io, NestedMap &nm) {
2609 io.mapRequired("Simple", nm.Simple, nm.Context);
2615 TEST(YAMLIO, TestMapWithContext) {
2616 MappingContext Context;
2617 NestedMap Nested(Context);
2618 std::string out;
2619 llvm::raw_string_ostream ostr(out);
2621 Output yout(ostr, nullptr, 15);
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);
2634 out.clear();
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();
2651 LLVM_YAML_IS_STRING_MAP(int)
2653 TEST(YAMLIO, TestCustomMapping) {
2654 std::map<std::string, int> x;
2656 std::string out;
2657 llvm::raw_string_ostream ostr(out);
2658 Output xout(ostr, nullptr, 0);
2660 xout << x;
2661 ostr.flush();
2662 EXPECT_EQ("---\n"
2663 "{}\n"
2664 "...\n",
2665 out);
2667 x["foo"] = 1;
2668 x["bar"] = 2;
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);
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"]);
2687 LLVM_YAML_IS_STRING_MAP(FooBar)
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;
2696 std::string out;
2697 llvm::raw_string_ostream ostr(out);
2698 Output xout(ostr, nullptr, 0);
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);
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);
2722 struct FooBarMapMap {
2723 std::map<std::string, FooBar> fbm;
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);
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");
2745 TEST(YAMLIO, TestEmptySequenceWrite) {
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");
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");
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);
2770 llvm::yaml::EmptyContext Ctx;
2771 yamlize(xout, Input, true, Ctx);
2773 ostr.flush();
2775 // Make a separate StringRef so we get nice byte-by-byte output.
2776 llvm::StringRef Got(out);
2777 EXPECT_EQ(Expected, Got);
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\"");
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.
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\"");
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"));
2821 EXPECT_TRUE(isNumeric(".nan"));
2822 EXPECT_TRUE(isNumeric(".NaN"));
2823 EXPECT_TRUE(isNumeric(".NAN"));
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"));
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"));
2838 EXPECT_TRUE(isNumeric("2.3e4"));
2839 EXPECT_TRUE(isNumeric("-2E+05"));
2840 EXPECT_TRUE(isNumeric("+12e03"));
2841 EXPECT_TRUE(isNumeric("6.8523015e+5"));
2843 EXPECT_TRUE(isNumeric("1.e+1"));
2844 EXPECT_TRUE(isNumeric(".0e+1"));
2846 EXPECT_TRUE(isNumeric("0x2aF3"));
2847 EXPECT_TRUE(isNumeric("0o01234567"));
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"));
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"));
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"));
2872 // Deprecated formats: as for YAML 1.2 specification, the following are not
2873 // valid numbers anymore:
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"));
2884 //===----------------------------------------------------------------------===//
2885 // Test PolymorphicTraits and TaggedScalarTraits
2886 //===----------------------------------------------------------------------===//
2888 struct Poly {
2889 enum NodeKind {
2890 NK_Scalar,
2891 NK_Seq,
2892 NK_Map,
2893 } Kind;
2895 Poly(NodeKind Kind) : Kind(Kind) {}
2897 virtual ~Poly() = default;
2899 NodeKind getKind() const { return Kind; }
2902 struct Scalar : Poly {
2903 enum ScalarKind {
2904 SK_Unknown,
2905 SK_Double,
2906 SK_Bool,
2907 } SKind;
2909 union {
2910 double DoubleValue;
2911 bool BoolValue;
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) {}
2920 static bool classof(const Poly *N) { return N->getKind() == NK_Scalar; }
2923 struct Seq : Poly, std::vector<std::unique_ptr<Poly>> {
2924 Seq() : Poly(NK_Seq) {}
2926 static bool classof(const Poly *N) { return N->getKind() == NK_Seq; }
2929 struct Map : Poly, llvm::StringMap<std::unique_ptr<Poly>> {
2930 Map() : Poly(NK_Map) {}
2932 static bool classof(const Poly *N) { return N->getKind() == NK_Map; }
2935 namespace llvm {
2936 namespace yaml {
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");
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());
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());
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());
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;
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);
3000 llvm_unreachable("unknown scalar kind");
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);
3012 llvm_unreachable("unknown scalar kind");
3016 template <> struct CustomMappingTraits<Map> {
3017 static void inputOne(IO &IO, StringRef Key, Map &M) {
3018 IO.mapRequired(Key.str().c_str(), M[Key]);
3021 static void output(IO &IO, Map &M) {
3022 for (auto &N : M)
3023 IO.mapRequired(N.getKey().str().c_str(), N.getValue());
3027 template <> struct SequenceTraits<Seq> {
3028 static size_t size(IO &IO, Seq &A) { return A.size(); }
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];
3037 } // namespace yaml
3038 } // namespace llvm
3040 TEST(YAMLIO, TestReadWritePolymorphicScalar) {
3041 std::string intermediate;
3042 std::unique_ptr<Poly> node = std::make_unique<Scalar>(true);
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
3053 TEST(YAMLIO, TestReadWritePolymorphicSeq) {
3054 std::string intermediate;
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);
3061 llvm::raw_string_ostream ostr(intermediate);
3062 Output yout(ostr);
3063 yout << node;
3066 Input yin(intermediate);
3067 std::unique_ptr<Poly> node;
3068 yin >> node;
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);
3085 TEST(YAMLIO, TestReadWritePolymorphicMap) {
3086 std::string intermediate;
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);
3093 llvm::raw_string_ostream ostr(intermediate);
3094 Output yout(ostr);
3095 yout << node;
3098 Input yin(intermediate);
3099 std::unique_ptr<Poly> node;
3100 yin >> node;
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);
3116 TEST(YAMLIO, TestAnchorMapError) {
3117 Input yin("& & &: ");
3118 yin.setCurrentDocument();
3119 EXPECT_TRUE(yin.error());
3122 TEST(YAMLIO, TestFlowSequenceTokenErrors) {
3123 Input yin(",");
3124 EXPECT_FALSE(yin.setCurrentDocument());
3125 EXPECT_TRUE(yin.error());
3127 Input yin2("]");
3128 EXPECT_FALSE(yin2.setCurrentDocument());
3129 EXPECT_TRUE(yin2.error());
3131 Input yin3("}");
3132 EXPECT_FALSE(yin3.setCurrentDocument());
3133 EXPECT_TRUE(yin3.error());
3136 TEST(YAMLIO, TestDirectiveMappingNoValue) {
3137 Input yin("%YAML\n{5:");
3138 EXPECT_FALSE(yin.setCurrentDocument());
3139 EXPECT_TRUE(yin.error());
3141 Input yin2("%TAG\n'\x98!< :\n");
3142 yin2.setCurrentDocument();
3143 EXPECT_TRUE(yin2.error());
3146 TEST(YAMLIO, TestUnescapeInfiniteLoop) {
3147 Input yin("\"\\u\\^#\\\\\"");
3148 yin.setCurrentDocument();
3149 EXPECT_TRUE(yin.error());
3152 TEST(YAMLIO, TestScannerUnexpectedCharacter) {
3153 Input yin("!<$\x9F.");
3154 EXPECT_FALSE(yin.setCurrentDocument());
3155 EXPECT_TRUE(yin.error());
3158 TEST(YAMLIO, TestUnknownDirective) {
3159 Input yin("%");
3160 EXPECT_FALSE(yin.setCurrentDocument());
3161 EXPECT_TRUE(yin.error());
3163 Input yin2("%)");
3164 EXPECT_FALSE(yin2.setCurrentDocument());
3165 EXPECT_TRUE(yin2.error());
3168 TEST(YAMLIO, TestEmptyAlias) {
3169 Input yin("&");
3170 EXPECT_FALSE(yin.setCurrentDocument());
3171 EXPECT_TRUE(yin.error());
3174 TEST(YAMLIO, TestEmptyAnchor) {
3175 Input yin("*");
3176 EXPECT_FALSE(yin.setCurrentDocument());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());