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