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