Recover gracefully when deserializing invalid YAML input.
[oota-llvm.git] / unittests / Support / YAMLIOTest.cpp
1 //===- unittest/Support/YAMLIOTest.cpp ------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ADT/SmallString.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/Casting.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/YAMLTraits.h"
15 #include "gtest/gtest.h"
16
17
18 using llvm::yaml::Input;
19 using llvm::yaml::Output;
20 using llvm::yaml::IO;
21 using llvm::yaml::MappingTraits;
22 using llvm::yaml::MappingNormalization;
23 using llvm::yaml::ScalarTraits;
24 using llvm::yaml::Hex8;
25 using llvm::yaml::Hex16;
26 using llvm::yaml::Hex32;
27 using llvm::yaml::Hex64;
28
29
30 //===----------------------------------------------------------------------===//
31 //  Test MappingTraits
32 //===----------------------------------------------------------------------===//
33
34 struct FooBar {
35   int foo;
36   int bar;
37 };
38 typedef std::vector<FooBar> FooBarSequence;
39
40 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
41
42
43 namespace llvm {
44 namespace yaml {
45   template <>
46   struct MappingTraits<FooBar> {
47     static void mapping(IO &io, FooBar& fb) {
48       io.mapRequired("foo",    fb.foo);
49       io.mapRequired("bar",    fb.bar);
50     }
51   };
52 }
53 }
54
55
56 //
57 // Test the reading of a yaml mapping
58 //
59 TEST(YAMLIO, TestMapRead) {
60   FooBar doc;
61   {
62     Input yin("---\nfoo:  3\nbar:  5\n...\n");
63     yin >> doc;
64
65     EXPECT_FALSE(yin.error());
66     EXPECT_EQ(doc.foo, 3);
67     EXPECT_EQ(doc.bar, 5);
68   }
69
70   {
71     Input yin("{foo: 3, bar: 5}");
72     yin >> doc;
73
74     EXPECT_FALSE(yin.error());
75     EXPECT_EQ(doc.foo, 3);
76     EXPECT_EQ(doc.bar, 5);
77   }
78 }
79
80 //
81 // Test the reading of a yaml sequence of mappings
82 //
83 TEST(YAMLIO, TestSequenceMapRead) {
84   FooBarSequence seq;
85   Input yin("---\n - foo:  3\n   bar:  5\n - foo:  7\n   bar:  9\n...\n");
86   yin >> seq;
87
88   EXPECT_FALSE(yin.error());
89   EXPECT_EQ(seq.size(), 2UL);
90   FooBar& map1 = seq[0];
91   FooBar& map2 = seq[1];
92   EXPECT_EQ(map1.foo, 3);
93   EXPECT_EQ(map1.bar, 5);
94   EXPECT_EQ(map2.foo, 7);
95   EXPECT_EQ(map2.bar, 9);
96 }
97
98
99 //
100 // Test writing then reading back a sequence of mappings
101 //
102 TEST(YAMLIO, TestSequenceMapWriteAndRead) {
103   std::string intermediate;
104   {
105     FooBar entry1;
106     entry1.foo = 10;
107     entry1.bar = -3;
108     FooBar entry2;
109     entry2.foo = 257;
110     entry2.bar = 0;
111     FooBarSequence seq;
112     seq.push_back(entry1);
113     seq.push_back(entry2);
114
115     llvm::raw_string_ostream ostr(intermediate);
116     Output yout(ostr);
117     yout << seq;
118   }
119
120   {
121     Input yin(intermediate);
122     FooBarSequence seq2;
123     yin >> seq2;
124
125     EXPECT_FALSE(yin.error());
126     EXPECT_EQ(seq2.size(), 2UL);
127     FooBar& map1 = seq2[0];
128     FooBar& map2 = seq2[1];
129     EXPECT_EQ(map1.foo, 10);
130     EXPECT_EQ(map1.bar, -3);
131     EXPECT_EQ(map2.foo, 257);
132     EXPECT_EQ(map2.bar, 0);
133   }
134 }
135
136
137 //===----------------------------------------------------------------------===//
138 //  Test built-in types
139 //===----------------------------------------------------------------------===//
140
141 struct BuiltInTypes {
142   llvm::StringRef str;
143   uint64_t        u64;
144   uint32_t        u32;
145   uint16_t        u16;
146   uint8_t         u8;
147   bool            b;
148   int64_t         s64;
149   int32_t         s32;
150   int16_t         s16;
151   int8_t          s8;
152   float           f;
153   double          d;
154   Hex8            h8;
155   Hex16           h16;
156   Hex32           h32;
157   Hex64           h64;
158 };
159
160 namespace llvm {
161 namespace yaml {
162   template <>
163   struct MappingTraits<BuiltInTypes> {
164     static void mapping(IO &io, BuiltInTypes& bt) {
165       io.mapRequired("str",      bt.str);
166       io.mapRequired("u64",      bt.u64);
167       io.mapRequired("u32",      bt.u32);
168       io.mapRequired("u16",      bt.u16);
169       io.mapRequired("u8",       bt.u8);
170       io.mapRequired("b",        bt.b);
171       io.mapRequired("s64",      bt.s64);
172       io.mapRequired("s32",      bt.s32);
173       io.mapRequired("s16",      bt.s16);
174       io.mapRequired("s8",       bt.s8);
175       io.mapRequired("f",        bt.f);
176       io.mapRequired("d",        bt.d);
177       io.mapRequired("h8",       bt.h8);
178       io.mapRequired("h16",      bt.h16);
179       io.mapRequired("h32",      bt.h32);
180       io.mapRequired("h64",      bt.h64);
181     }
182   };
183 }
184 }
185
186
187 //
188 // Test the reading of all built-in scalar conversions
189 //
190 TEST(YAMLIO, TestReadBuiltInTypes) {
191   BuiltInTypes map;
192   Input yin("---\n"
193             "str:      hello there\n"
194             "u64:      5000000000\n"
195             "u32:      4000000000\n"
196             "u16:      65000\n"
197             "u8:       255\n"
198             "b:        false\n"
199             "s64:      -5000000000\n"
200             "s32:      -2000000000\n"
201             "s16:      -32000\n"
202             "s8:       -127\n"
203             "f:        137.125\n"
204             "d:        -2.8625\n"
205             "h8:       0xFF\n"
206             "h16:      0x8765\n"
207             "h32:      0xFEDCBA98\n"
208             "h64:      0xFEDCBA9876543210\n"
209            "...\n");
210   yin >> map;
211
212   EXPECT_FALSE(yin.error());
213   EXPECT_TRUE(map.str.equals("hello there"));
214   EXPECT_EQ(map.u64, 5000000000ULL);
215   EXPECT_EQ(map.u32, 4000000000U);
216   EXPECT_EQ(map.u16, 65000);
217   EXPECT_EQ(map.u8,  255);
218   EXPECT_EQ(map.b,   false);
219   EXPECT_EQ(map.s64, -5000000000LL);
220   EXPECT_EQ(map.s32, -2000000000L);
221   EXPECT_EQ(map.s16, -32000);
222   EXPECT_EQ(map.s8,  -127);
223   EXPECT_EQ(map.f,   137.125);
224   EXPECT_EQ(map.d,   -2.8625);
225   EXPECT_EQ(map.h8,  Hex8(255));
226   EXPECT_EQ(map.h16, Hex16(0x8765));
227   EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
228   EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
229 }
230
231
232 //
233 // Test writing then reading back all built-in scalar types
234 //
235 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
236   std::string intermediate;
237   {
238     BuiltInTypes map;
239     map.str = "one two";
240     map.u64 = 6000000000ULL;
241     map.u32 = 3000000000U;
242     map.u16 = 50000;
243     map.u8  = 254;
244     map.b   = true;
245     map.s64 = -6000000000LL;
246     map.s32 = -2000000000;
247     map.s16 = -32000;
248     map.s8  = -128;
249     map.f   = 3.25;
250     map.d   = -2.8625;
251     map.h8  = 254;
252     map.h16 = 50000;
253     map.h32 = 3000000000U;
254     map.h64 = 6000000000LL;
255
256     llvm::raw_string_ostream ostr(intermediate);
257     Output yout(ostr);
258     yout << map;
259   }
260
261   {
262     Input yin(intermediate);
263     BuiltInTypes map;
264     yin >> map;
265
266     EXPECT_FALSE(yin.error());
267     EXPECT_TRUE(map.str.equals("one two"));
268     EXPECT_EQ(map.u64,      6000000000ULL);
269     EXPECT_EQ(map.u32,      3000000000U);
270     EXPECT_EQ(map.u16,      50000);
271     EXPECT_EQ(map.u8,       254);
272     EXPECT_EQ(map.b,        true);
273     EXPECT_EQ(map.s64,      -6000000000LL);
274     EXPECT_EQ(map.s32,      -2000000000L);
275     EXPECT_EQ(map.s16,      -32000);
276     EXPECT_EQ(map.s8,       -128);
277     EXPECT_EQ(map.f,        3.25);
278     EXPECT_EQ(map.d,        -2.8625);
279     EXPECT_EQ(map.h8,       Hex8(254));
280     EXPECT_EQ(map.h16,      Hex16(50000));
281     EXPECT_EQ(map.h32,      Hex32(3000000000U));
282     EXPECT_EQ(map.h64,      Hex64(6000000000LL));
283   }
284 }
285
286 struct StringTypes {
287   llvm::StringRef str1;
288   llvm::StringRef str2;
289   llvm::StringRef str3;
290   llvm::StringRef str4;
291   llvm::StringRef str5;
292 };
293
294 namespace llvm {
295 namespace yaml {
296   template <>
297   struct MappingTraits<StringTypes> {
298     static void mapping(IO &io, StringTypes& st) {
299       io.mapRequired("str1",      st.str1);
300       io.mapRequired("str2",      st.str2);
301       io.mapRequired("str3",      st.str3);
302       io.mapRequired("str4",      st.str4);
303       io.mapRequired("str5",      st.str5);
304     }
305   };
306 }
307 }
308
309 TEST(YAMLIO, TestReadWriteStringTypes) {
310   std::string intermediate;
311   {
312     StringTypes map;
313     map.str1 = "'aaa";
314     map.str2 = "\"bbb";
315     map.str3 = "`ccc";
316     map.str4 = "@ddd";
317     map.str5 = "";
318
319     llvm::raw_string_ostream ostr(intermediate);
320     Output yout(ostr);
321     yout << map;
322   }
323
324   llvm::StringRef flowOut(intermediate);
325   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
326   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
327   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
328   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
329   EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
330
331   {
332     Input yin(intermediate);
333     StringTypes map;
334     yin >> map;
335
336     EXPECT_FALSE(yin.error());
337     EXPECT_TRUE(map.str1.equals("'aaa"));
338     EXPECT_TRUE(map.str2.equals("\"bbb"));
339     EXPECT_TRUE(map.str3.equals("`ccc"));
340     EXPECT_TRUE(map.str4.equals("@ddd"));
341     EXPECT_TRUE(map.str5.equals(""));
342   }
343 }
344
345 //===----------------------------------------------------------------------===//
346 //  Test ScalarEnumerationTraits
347 //===----------------------------------------------------------------------===//
348
349 enum Colors {
350     cRed,
351     cBlue,
352     cGreen,
353     cYellow
354 };
355
356 struct ColorMap {
357   Colors      c1;
358   Colors      c2;
359   Colors      c3;
360   Colors      c4;
361   Colors      c5;
362   Colors      c6;
363 };
364
365 namespace llvm {
366 namespace yaml {
367   template <>
368   struct ScalarEnumerationTraits<Colors> {
369     static void enumeration(IO &io, Colors &value) {
370       io.enumCase(value, "red",   cRed);
371       io.enumCase(value, "blue",  cBlue);
372       io.enumCase(value, "green", cGreen);
373       io.enumCase(value, "yellow",cYellow);
374     }
375   };
376   template <>
377   struct MappingTraits<ColorMap> {
378     static void mapping(IO &io, ColorMap& c) {
379       io.mapRequired("c1", c.c1);
380       io.mapRequired("c2", c.c2);
381       io.mapRequired("c3", c.c3);
382       io.mapOptional("c4", c.c4, cBlue);   // supplies default
383       io.mapOptional("c5", c.c5, cYellow); // supplies default
384       io.mapOptional("c6", c.c6, cRed);    // supplies default
385     }
386   };
387 }
388 }
389
390
391 //
392 // Test reading enumerated scalars
393 //
394 TEST(YAMLIO, TestEnumRead) {
395   ColorMap map;
396   Input yin("---\n"
397             "c1:  blue\n"
398             "c2:  red\n"
399             "c3:  green\n"
400             "c5:  yellow\n"
401             "...\n");
402   yin >> map;
403
404   EXPECT_FALSE(yin.error());
405   EXPECT_EQ(cBlue,  map.c1);
406   EXPECT_EQ(cRed,   map.c2);
407   EXPECT_EQ(cGreen, map.c3);
408   EXPECT_EQ(cBlue,  map.c4);  // tests default
409   EXPECT_EQ(cYellow,map.c5);  // tests overridden
410   EXPECT_EQ(cRed,   map.c6);  // tests default
411 }
412
413
414
415 //===----------------------------------------------------------------------===//
416 //  Test ScalarBitSetTraits
417 //===----------------------------------------------------------------------===//
418
419 enum MyFlags {
420   flagNone    = 0,
421   flagBig     = 1 << 0,
422   flagFlat    = 1 << 1,
423   flagRound   = 1 << 2,
424   flagPointy  = 1 << 3
425 };
426 inline MyFlags operator|(MyFlags a, MyFlags b) {
427   return static_cast<MyFlags>(
428                       static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
429 }
430
431 struct FlagsMap {
432   MyFlags     f1;
433   MyFlags     f2;
434   MyFlags     f3;
435   MyFlags     f4;
436 };
437
438
439 namespace llvm {
440 namespace yaml {
441   template <>
442   struct ScalarBitSetTraits<MyFlags> {
443     static void bitset(IO &io, MyFlags &value) {
444       io.bitSetCase(value, "big",   flagBig);
445       io.bitSetCase(value, "flat",  flagFlat);
446       io.bitSetCase(value, "round", flagRound);
447       io.bitSetCase(value, "pointy",flagPointy);
448     }
449   };
450   template <>
451   struct MappingTraits<FlagsMap> {
452     static void mapping(IO &io, FlagsMap& c) {
453       io.mapRequired("f1", c.f1);
454       io.mapRequired("f2", c.f2);
455       io.mapRequired("f3", c.f3);
456       io.mapOptional("f4", c.f4, MyFlags(flagRound));
457      }
458   };
459 }
460 }
461
462
463 //
464 // Test reading flow sequence representing bit-mask values
465 //
466 TEST(YAMLIO, TestFlagsRead) {
467   FlagsMap map;
468   Input yin("---\n"
469             "f1:  [ big ]\n"
470             "f2:  [ round, flat ]\n"
471             "f3:  []\n"
472             "...\n");
473   yin >> map;
474
475   EXPECT_FALSE(yin.error());
476   EXPECT_EQ(flagBig,              map.f1);
477   EXPECT_EQ(flagRound|flagFlat,   map.f2);
478   EXPECT_EQ(flagNone,             map.f3);  // check empty set
479   EXPECT_EQ(flagRound,            map.f4);  // check optional key
480 }
481
482
483 //
484 // Test writing then reading back bit-mask values
485 //
486 TEST(YAMLIO, TestReadWriteFlags) {
487   std::string intermediate;
488   {
489     FlagsMap map;
490     map.f1 = flagBig;
491     map.f2 = flagRound | flagFlat;
492     map.f3 = flagNone;
493     map.f4 = flagNone;
494
495     llvm::raw_string_ostream ostr(intermediate);
496     Output yout(ostr);
497     yout << map;
498   }
499
500   {
501     Input yin(intermediate);
502     FlagsMap map2;
503     yin >> map2;
504
505     EXPECT_FALSE(yin.error());
506     EXPECT_EQ(flagBig,              map2.f1);
507     EXPECT_EQ(flagRound|flagFlat,   map2.f2);
508     EXPECT_EQ(flagNone,             map2.f3);
509     //EXPECT_EQ(flagRound,            map2.f4);  // check optional key
510   }
511 }
512
513
514
515 //===----------------------------------------------------------------------===//
516 //  Test ScalarTraits
517 //===----------------------------------------------------------------------===//
518
519 struct MyCustomType {
520   int length;
521   int width;
522 };
523
524 struct MyCustomTypeMap {
525   MyCustomType     f1;
526   MyCustomType     f2;
527   int              f3;
528 };
529
530
531 namespace llvm {
532 namespace yaml {
533   template <>
534   struct MappingTraits<MyCustomTypeMap> {
535     static void mapping(IO &io, MyCustomTypeMap& s) {
536       io.mapRequired("f1", s.f1);
537       io.mapRequired("f2", s.f2);
538       io.mapRequired("f3", s.f3);
539      }
540   };
541   // MyCustomType is formatted as a yaml scalar.  A value of
542   // {length=3, width=4} would be represented in yaml as "3 by 4".
543   template<>
544   struct ScalarTraits<MyCustomType> {
545     static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
546       out << llvm::format("%d by %d", value.length, value.width);
547     }
548     static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
549       size_t byStart = scalar.find("by");
550       if ( byStart != StringRef::npos ) {
551         StringRef lenStr = scalar.slice(0, byStart);
552         lenStr = lenStr.rtrim();
553         if ( lenStr.getAsInteger(0, value.length) ) {
554           return "malformed length";
555         }
556         StringRef widthStr = scalar.drop_front(byStart+2);
557         widthStr = widthStr.ltrim();
558         if ( widthStr.getAsInteger(0, value.width) ) {
559           return "malformed width";
560         }
561         return StringRef();
562       }
563       else {
564           return "malformed by";
565       }
566     }
567   };
568 }
569 }
570
571
572 //
573 // Test writing then reading back custom values
574 //
575 TEST(YAMLIO, TestReadWriteMyCustomType) {
576   std::string intermediate;
577   {
578     MyCustomTypeMap map;
579     map.f1.length = 1;
580     map.f1.width  = 4;
581     map.f2.length = 100;
582     map.f2.width  = 400;
583     map.f3 = 10;
584
585     llvm::raw_string_ostream ostr(intermediate);
586     Output yout(ostr);
587     yout << map;
588   }
589
590   {
591     Input yin(intermediate);
592     MyCustomTypeMap map2;
593     yin >> map2;
594
595     EXPECT_FALSE(yin.error());
596     EXPECT_EQ(1,      map2.f1.length);
597     EXPECT_EQ(4,      map2.f1.width);
598     EXPECT_EQ(100,    map2.f2.length);
599     EXPECT_EQ(400,    map2.f2.width);
600     EXPECT_EQ(10,     map2.f3);
601   }
602 }
603
604
605 //===----------------------------------------------------------------------===//
606 //  Test flow sequences
607 //===----------------------------------------------------------------------===//
608
609 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
610 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
611 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef)
612
613 namespace llvm {
614 namespace yaml {
615   template<>
616   struct ScalarTraits<MyNumber> {
617     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
618       out << value;
619     }
620
621     static StringRef input(StringRef scalar, void *, MyNumber &value) {
622       long long n;
623       if ( getAsSignedInteger(scalar, 0, n) )
624         return "invalid number";
625       value = n;
626       return StringRef();
627     }
628   };
629 }
630 }
631
632 struct NameAndNumbers {
633   llvm::StringRef               name;
634   std::vector<llvm::StringRef>  strings;
635   std::vector<MyNumber>         single;
636   std::vector<MyNumber>         numbers;
637 };
638
639 namespace llvm {
640 namespace yaml {
641   template <>
642   struct MappingTraits<NameAndNumbers> {
643     static void mapping(IO &io, NameAndNumbers& nn) {
644       io.mapRequired("name",     nn.name);
645       io.mapRequired("strings",  nn.strings);
646       io.mapRequired("single",   nn.single);
647       io.mapRequired("numbers",  nn.numbers);
648     }
649   };
650 }
651 }
652
653
654 //
655 // Test writing then reading back custom values
656 //
657 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
658   std::string intermediate;
659   {
660     NameAndNumbers map;
661     map.name  = "hello";
662     map.strings.push_back(llvm::StringRef("one"));
663     map.strings.push_back(llvm::StringRef("two"));
664     map.single.push_back(1);
665     map.numbers.push_back(10);
666     map.numbers.push_back(-30);
667     map.numbers.push_back(1024);
668
669     llvm::raw_string_ostream ostr(intermediate);
670     Output yout(ostr);
671     yout << map;
672
673     // Verify sequences were written in flow style
674     ostr.flush();
675     llvm::StringRef flowOut(intermediate);
676     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
677     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
678   }
679
680   {
681     Input yin(intermediate);
682     NameAndNumbers map2;
683     yin >> map2;
684
685     EXPECT_FALSE(yin.error());
686     EXPECT_TRUE(map2.name.equals("hello"));
687     EXPECT_EQ(map2.strings.size(), 2UL);
688     EXPECT_TRUE(map2.strings[0].equals("one"));
689     EXPECT_TRUE(map2.strings[1].equals("two"));
690     EXPECT_EQ(map2.single.size(), 1UL);
691     EXPECT_EQ(1,       map2.single[0]);
692     EXPECT_EQ(map2.numbers.size(), 3UL);
693     EXPECT_EQ(10,      map2.numbers[0]);
694     EXPECT_EQ(-30,     map2.numbers[1]);
695     EXPECT_EQ(1024,    map2.numbers[2]);
696   }
697 }
698
699
700 //===----------------------------------------------------------------------===//
701 //  Test normalizing/denormalizing
702 //===----------------------------------------------------------------------===//
703
704 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
705
706 typedef std::vector<TotalSeconds> SecondsSequence;
707
708 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
709
710
711 namespace llvm {
712 namespace yaml {
713   template <>
714   struct MappingTraits<TotalSeconds> {
715
716     class NormalizedSeconds {
717     public:
718       NormalizedSeconds(IO &io)
719         : hours(0), minutes(0), seconds(0) {
720       }
721       NormalizedSeconds(IO &, TotalSeconds &secs)
722         : hours(secs/3600),
723           minutes((secs - (hours*3600))/60),
724           seconds(secs % 60) {
725       }
726       TotalSeconds denormalize(IO &) {
727         return TotalSeconds(hours*3600 + minutes*60 + seconds);
728       }
729
730       uint32_t     hours;
731       uint8_t      minutes;
732       uint8_t      seconds;
733     };
734
735     static void mapping(IO &io, TotalSeconds &secs) {
736       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
737
738       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
739       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
740       io.mapRequired("seconds",  keys->seconds);
741     }
742   };
743 }
744 }
745
746
747 //
748 // Test the reading of a yaml sequence of mappings
749 //
750 TEST(YAMLIO, TestReadMySecondsSequence) {
751   SecondsSequence seq;
752   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
753   yin >> seq;
754
755   EXPECT_FALSE(yin.error());
756   EXPECT_EQ(seq.size(), 2UL);
757   EXPECT_EQ(seq[0], 3605U);
758   EXPECT_EQ(seq[1], 59U);
759 }
760
761
762 //
763 // Test writing then reading back custom values
764 //
765 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
766   std::string intermediate;
767   {
768     SecondsSequence seq;
769     seq.push_back(4000);
770     seq.push_back(500);
771     seq.push_back(59);
772
773     llvm::raw_string_ostream ostr(intermediate);
774     Output yout(ostr);
775     yout << seq;
776   }
777   {
778     Input yin(intermediate);
779     SecondsSequence seq2;
780     yin >> seq2;
781
782     EXPECT_FALSE(yin.error());
783     EXPECT_EQ(seq2.size(), 3UL);
784     EXPECT_EQ(seq2[0], 4000U);
785     EXPECT_EQ(seq2[1], 500U);
786     EXPECT_EQ(seq2[2], 59U);
787   }
788 }
789
790
791 //===----------------------------------------------------------------------===//
792 //  Test dynamic typing
793 //===----------------------------------------------------------------------===//
794
795 enum AFlags {
796     a1,
797     a2,
798     a3
799 };
800
801 enum BFlags {
802     b1,
803     b2,
804     b3
805 };
806
807 enum Kind {
808     kindA,
809     kindB
810 };
811
812 struct KindAndFlags {
813   KindAndFlags() : kind(kindA), flags(0) { }
814   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
815   Kind        kind;
816   uint32_t    flags;
817 };
818
819 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
820
821 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
822
823 namespace llvm {
824 namespace yaml {
825   template <>
826   struct ScalarEnumerationTraits<AFlags> {
827     static void enumeration(IO &io, AFlags &value) {
828       io.enumCase(value, "a1",  a1);
829       io.enumCase(value, "a2",  a2);
830       io.enumCase(value, "a3",  a3);
831     }
832   };
833   template <>
834   struct ScalarEnumerationTraits<BFlags> {
835     static void enumeration(IO &io, BFlags &value) {
836       io.enumCase(value, "b1",  b1);
837       io.enumCase(value, "b2",  b2);
838       io.enumCase(value, "b3",  b3);
839     }
840   };
841   template <>
842   struct ScalarEnumerationTraits<Kind> {
843     static void enumeration(IO &io, Kind &value) {
844       io.enumCase(value, "A",  kindA);
845       io.enumCase(value, "B",  kindB);
846     }
847   };
848   template <>
849   struct MappingTraits<KindAndFlags> {
850     static void mapping(IO &io, KindAndFlags& kf) {
851       io.mapRequired("kind",  kf.kind);
852       // Type of "flags" field varies depending on "kind" field.
853       // Use memcpy here to avoid breaking strict aliasing rules.
854       if (kf.kind == kindA) {
855         AFlags aflags = static_cast<AFlags>(kf.flags);
856         io.mapRequired("flags", aflags);
857         kf.flags = aflags;
858       } else {
859         BFlags bflags = static_cast<BFlags>(kf.flags);
860         io.mapRequired("flags", bflags);
861         kf.flags = bflags;
862       }
863     }
864   };
865 }
866 }
867
868
869 //
870 // Test the reading of a yaml sequence dynamic types
871 //
872 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
873   KindAndFlagsSequence seq;
874   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
875   yin >> seq;
876
877   EXPECT_FALSE(yin.error());
878   EXPECT_EQ(seq.size(), 2UL);
879   EXPECT_EQ(seq[0].kind,  kindA);
880   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
881   EXPECT_EQ(seq[1].kind,  kindB);
882   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
883 }
884
885 //
886 // Test writing then reading back dynamic types
887 //
888 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
889   std::string intermediate;
890   {
891     KindAndFlagsSequence seq;
892     seq.push_back(KindAndFlags(kindA,a1));
893     seq.push_back(KindAndFlags(kindB,b1));
894     seq.push_back(KindAndFlags(kindA,a2));
895     seq.push_back(KindAndFlags(kindB,b2));
896     seq.push_back(KindAndFlags(kindA,a3));
897
898     llvm::raw_string_ostream ostr(intermediate);
899     Output yout(ostr);
900     yout << seq;
901   }
902   {
903     Input yin(intermediate);
904     KindAndFlagsSequence seq2;
905     yin >> seq2;
906
907     EXPECT_FALSE(yin.error());
908     EXPECT_EQ(seq2.size(), 5UL);
909     EXPECT_EQ(seq2[0].kind,  kindA);
910     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
911     EXPECT_EQ(seq2[1].kind,  kindB);
912     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
913     EXPECT_EQ(seq2[2].kind,  kindA);
914     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
915     EXPECT_EQ(seq2[3].kind,  kindB);
916     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
917     EXPECT_EQ(seq2[4].kind,  kindA);
918     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
919   }
920 }
921
922
923 //===----------------------------------------------------------------------===//
924 //  Test document list
925 //===----------------------------------------------------------------------===//
926
927 struct FooBarMap {
928   int foo;
929   int bar;
930 };
931 typedef std::vector<FooBarMap> FooBarMapDocumentList;
932
933 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
934
935
936 namespace llvm {
937 namespace yaml {
938   template <>
939   struct MappingTraits<FooBarMap> {
940     static void mapping(IO &io, FooBarMap& fb) {
941       io.mapRequired("foo",    fb.foo);
942       io.mapRequired("bar",    fb.bar);
943     }
944   };
945 }
946 }
947
948
949 //
950 // Test the reading of a yaml mapping
951 //
952 TEST(YAMLIO, TestDocRead) {
953   FooBarMap doc;
954   Input yin("---\nfoo:  3\nbar:  5\n...\n");
955   yin >> doc;
956
957   EXPECT_FALSE(yin.error());
958   EXPECT_EQ(doc.foo, 3);
959   EXPECT_EQ(doc.bar,5);
960 }
961
962
963
964 //
965 // Test writing then reading back a sequence of mappings
966 //
967 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
968   std::string intermediate;
969   {
970     FooBarMap doc1;
971     doc1.foo = 10;
972     doc1.bar = -3;
973     FooBarMap doc2;
974     doc2.foo = 257;
975     doc2.bar = 0;
976     std::vector<FooBarMap> docList;
977     docList.push_back(doc1);
978     docList.push_back(doc2);
979
980     llvm::raw_string_ostream ostr(intermediate);
981     Output yout(ostr);
982     yout << docList;
983   }
984
985
986   {
987     Input yin(intermediate);
988     std::vector<FooBarMap> docList2;
989     yin >> docList2;
990
991     EXPECT_FALSE(yin.error());
992     EXPECT_EQ(docList2.size(), 2UL);
993     FooBarMap& map1 = docList2[0];
994     FooBarMap& map2 = docList2[1];
995     EXPECT_EQ(map1.foo, 10);
996     EXPECT_EQ(map1.bar, -3);
997     EXPECT_EQ(map2.foo, 257);
998     EXPECT_EQ(map2.bar, 0);
999   }
1000 }
1001
1002 //===----------------------------------------------------------------------===//
1003 //  Test document tags
1004 //===----------------------------------------------------------------------===//
1005
1006 struct MyDouble {
1007   MyDouble() : value(0.0) { }
1008   MyDouble(double x) : value(x) { }
1009   double value;
1010 };
1011
1012 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
1013
1014
1015 namespace llvm {
1016 namespace yaml {
1017   template <>
1018   struct MappingTraits<MyDouble> {
1019     static void mapping(IO &io, MyDouble &d) {
1020       if (io.mapTag("!decimal", true)) {
1021         mappingDecimal(io, d);
1022       } else if (io.mapTag("!fraction")) {
1023         mappingFraction(io, d);
1024       }
1025     }
1026     static void mappingDecimal(IO &io, MyDouble &d) {
1027       io.mapRequired("value", d.value);
1028     }
1029     static void mappingFraction(IO &io, MyDouble &d) {
1030         double num, denom;
1031         io.mapRequired("numerator",      num);
1032         io.mapRequired("denominator",    denom);
1033         // convert fraction to double
1034         d.value = num/denom;
1035     }
1036   };
1037  }
1038 }
1039
1040
1041 //
1042 // Test the reading of two different tagged yaml documents.
1043 //
1044 TEST(YAMLIO, TestTaggedDocuments) {
1045   std::vector<MyDouble> docList;
1046   Input yin("--- !decimal\nvalue:  3.0\n"
1047             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
1048   yin >> docList;
1049   EXPECT_FALSE(yin.error());
1050   EXPECT_EQ(docList.size(), 2UL);
1051   EXPECT_EQ(docList[0].value, 3.0);
1052   EXPECT_EQ(docList[1].value, 4.5);
1053 }
1054
1055
1056
1057 //
1058 // Test writing then reading back tagged documents
1059 //
1060 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1061   std::string intermediate;
1062   {
1063     MyDouble a(10.25);
1064     MyDouble b(-3.75);
1065     std::vector<MyDouble> docList;
1066     docList.push_back(a);
1067     docList.push_back(b);
1068
1069     llvm::raw_string_ostream ostr(intermediate);
1070     Output yout(ostr);
1071     yout << docList;
1072   }
1073
1074   {
1075     Input yin(intermediate);
1076     std::vector<MyDouble> docList2;
1077     yin >> docList2;
1078
1079     EXPECT_FALSE(yin.error());
1080     EXPECT_EQ(docList2.size(), 2UL);
1081     EXPECT_EQ(docList2[0].value, 10.25);
1082     EXPECT_EQ(docList2[1].value, -3.75);
1083   }
1084 }
1085
1086
1087 //===----------------------------------------------------------------------===//
1088 //  Test dyn_cast<> on IO object 
1089 //===----------------------------------------------------------------------===//
1090
1091 struct DynCast {
1092   int value;
1093 };
1094 typedef std::vector<DynCast> DynCastSequence;
1095
1096 LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast)
1097
1098 namespace llvm {
1099 namespace yaml {
1100   template <>
1101   struct MappingTraits<DynCast> {
1102     static void mapping(IO &io, DynCast& info) {
1103       // Change 10 to 13 when writing yaml.
1104       if (Output *output = dyn_cast<Output>(&io)) {
1105         (void)output;
1106         if (info.value == 10)
1107           info.value = 13;
1108       }
1109       io.mapRequired("value", info.value);
1110       // Change 20 to 23 when parsing yaml.
1111       if (Input *input = dyn_cast<Input>(&io)) {
1112         (void)input;
1113         if (info.value == 20)
1114           info.value = 23;
1115       }
1116     }
1117   };
1118 }
1119 }
1120
1121 //
1122 // Test writing then reading back a sequence of mappings
1123 //
1124 TEST(YAMLIO, TestDynCast) {
1125   std::string intermediate;
1126   {
1127     DynCast entry1;
1128     entry1.value = 10;
1129     DynCast entry2;
1130     entry2.value = 20;
1131     DynCast entry3;
1132     entry3.value = 30;
1133     DynCastSequence seq;
1134     seq.push_back(entry1);
1135     seq.push_back(entry2);
1136     seq.push_back(entry3);
1137
1138     llvm::raw_string_ostream ostr(intermediate);
1139     Output yout(ostr);
1140     yout << seq;
1141   }
1142
1143   {
1144     Input yin(intermediate);
1145     DynCastSequence seq2;
1146     yin >> seq2;
1147
1148     EXPECT_FALSE(yin.error());
1149     EXPECT_EQ(seq2.size(), 3UL);
1150     EXPECT_EQ(seq2[0].value, 13);   // Verify changed to 13.
1151     EXPECT_EQ(seq2[1].value, 23);   // Verify changed to 23.
1152     EXPECT_EQ(seq2[2].value, 30);   // Verify stays same.
1153   }
1154 }
1155
1156
1157
1158 //===----------------------------------------------------------------------===//
1159 //  Test error handling
1160 //===----------------------------------------------------------------------===//
1161
1162
1163
1164 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
1165 }
1166
1167
1168 //
1169 // Test error handling of unknown enumerated scalar
1170 //
1171 TEST(YAMLIO, TestColorsReadError) {
1172   ColorMap map;
1173   Input yin("---\n"
1174             "c1:  blue\n"
1175             "c2:  purple\n"
1176             "c3:  green\n"
1177             "...\n",
1178             /*Ctxt=*/NULL,
1179             suppressErrorMessages);
1180   yin >> map;
1181   EXPECT_TRUE(yin.error());
1182 }
1183
1184
1185 //
1186 // Test error handling of flow sequence with unknown value
1187 //
1188 TEST(YAMLIO, TestFlagsReadError) {
1189   FlagsMap map;
1190   Input yin("---\n"
1191             "f1:  [ big ]\n"
1192             "f2:  [ round, hollow ]\n"
1193             "f3:  []\n"
1194             "...\n",
1195             /*Ctxt=*/NULL,
1196             suppressErrorMessages);
1197   yin >> map;
1198
1199   EXPECT_TRUE(yin.error());
1200 }
1201
1202
1203 //
1204 // Test error handling reading built-in uint8_t type
1205 //
1206 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
1207 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1208   std::vector<uint8_t> seq;
1209   Input yin("---\n"
1210             "- 255\n"
1211             "- 0\n"
1212             "- 257\n"
1213             "...\n",
1214             /*Ctxt=*/NULL,
1215             suppressErrorMessages);
1216   yin >> seq;
1217
1218   EXPECT_TRUE(yin.error());
1219 }
1220
1221
1222 //
1223 // Test error handling reading built-in uint16_t type
1224 //
1225 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
1226 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1227   std::vector<uint16_t> seq;
1228   Input yin("---\n"
1229             "- 65535\n"
1230             "- 0\n"
1231             "- 66000\n"
1232             "...\n",
1233             /*Ctxt=*/NULL,
1234             suppressErrorMessages);
1235   yin >> seq;
1236
1237   EXPECT_TRUE(yin.error());
1238 }
1239
1240
1241 //
1242 // Test error handling reading built-in uint32_t type
1243 //
1244 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
1245 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1246   std::vector<uint32_t> seq;
1247   Input yin("---\n"
1248             "- 4000000000\n"
1249             "- 0\n"
1250             "- 5000000000\n"
1251             "...\n",
1252             /*Ctxt=*/NULL,
1253             suppressErrorMessages);
1254   yin >> seq;
1255
1256   EXPECT_TRUE(yin.error());
1257 }
1258
1259
1260 //
1261 // Test error handling reading built-in uint64_t type
1262 //
1263 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
1264 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1265   std::vector<uint64_t> seq;
1266   Input yin("---\n"
1267             "- 18446744073709551615\n"
1268             "- 0\n"
1269             "- 19446744073709551615\n"
1270             "...\n",
1271             /*Ctxt=*/NULL,
1272             suppressErrorMessages);
1273   yin >> seq;
1274
1275   EXPECT_TRUE(yin.error());
1276 }
1277
1278
1279 //
1280 // Test error handling reading built-in int8_t type
1281 //
1282 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
1283 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1284   std::vector<int8_t> seq;
1285   Input yin("---\n"
1286             "- -128\n"
1287             "- 0\n"
1288             "- 127\n"
1289             "- 128\n"
1290            "...\n",
1291             /*Ctxt=*/NULL,
1292             suppressErrorMessages);
1293   yin >> seq;
1294
1295   EXPECT_TRUE(yin.error());
1296 }
1297
1298 //
1299 // Test error handling reading built-in int8_t type
1300 //
1301 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1302   std::vector<int8_t> seq;
1303   Input yin("---\n"
1304             "- -128\n"
1305             "- 0\n"
1306             "- 127\n"
1307             "- -129\n"
1308             "...\n",
1309             /*Ctxt=*/NULL,
1310             suppressErrorMessages);
1311   yin >> seq;
1312
1313   EXPECT_TRUE(yin.error());
1314 }
1315
1316
1317 //
1318 // Test error handling reading built-in int16_t type
1319 //
1320 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
1321 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1322   std::vector<int16_t> seq;
1323   Input yin("---\n"
1324             "- 32767\n"
1325             "- 0\n"
1326             "- -32768\n"
1327             "- -32769\n"
1328             "...\n",
1329             /*Ctxt=*/NULL,
1330             suppressErrorMessages);
1331   yin >> seq;
1332
1333   EXPECT_TRUE(yin.error());
1334 }
1335
1336
1337 //
1338 // Test error handling reading built-in int16_t type
1339 //
1340 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1341   std::vector<int16_t> seq;
1342   Input yin("---\n"
1343             "- 32767\n"
1344             "- 0\n"
1345             "- -32768\n"
1346             "- 32768\n"
1347             "...\n",
1348             /*Ctxt=*/NULL,
1349             suppressErrorMessages);
1350   yin >> seq;
1351
1352   EXPECT_TRUE(yin.error());
1353 }
1354
1355
1356 //
1357 // Test error handling reading built-in int32_t type
1358 //
1359 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
1360 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1361   std::vector<int32_t> seq;
1362   Input yin("---\n"
1363             "- 2147483647\n"
1364             "- 0\n"
1365             "- -2147483648\n"
1366             "- -2147483649\n"
1367             "...\n",
1368             /*Ctxt=*/NULL,
1369             suppressErrorMessages);
1370   yin >> seq;
1371
1372   EXPECT_TRUE(yin.error());
1373 }
1374
1375 //
1376 // Test error handling reading built-in int32_t type
1377 //
1378 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1379   std::vector<int32_t> seq;
1380   Input yin("---\n"
1381             "- 2147483647\n"
1382             "- 0\n"
1383             "- -2147483648\n"
1384             "- 2147483649\n"
1385             "...\n",
1386             /*Ctxt=*/NULL,
1387             suppressErrorMessages);
1388   yin >> seq;
1389
1390   EXPECT_TRUE(yin.error());
1391 }
1392
1393
1394 //
1395 // Test error handling reading built-in int64_t type
1396 //
1397 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
1398 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1399   std::vector<int64_t> seq;
1400   Input yin("---\n"
1401             "- -9223372036854775808\n"
1402             "- 0\n"
1403             "- 9223372036854775807\n"
1404             "- -9223372036854775809\n"
1405             "...\n",
1406             /*Ctxt=*/NULL,
1407             suppressErrorMessages);
1408   yin >> seq;
1409
1410   EXPECT_TRUE(yin.error());
1411 }
1412
1413 //
1414 // Test error handling reading built-in int64_t type
1415 //
1416 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1417   std::vector<int64_t> seq;
1418   Input yin("---\n"
1419             "- -9223372036854775808\n"
1420             "- 0\n"
1421             "- 9223372036854775807\n"
1422             "- 9223372036854775809\n"
1423             "...\n",
1424             /*Ctxt=*/NULL,
1425             suppressErrorMessages);
1426   yin >> seq;
1427
1428   EXPECT_TRUE(yin.error());
1429 }
1430
1431 //
1432 // Test error handling reading built-in float type
1433 //
1434 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
1435 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1436   std::vector<float> seq;
1437   Input yin("---\n"
1438             "- 0.0\n"
1439             "- 1000.1\n"
1440             "- -123.456\n"
1441             "- 1.2.3\n"
1442             "...\n",
1443             /*Ctxt=*/NULL,
1444             suppressErrorMessages);
1445   yin >> seq;
1446
1447   EXPECT_TRUE(yin.error());
1448 }
1449
1450 //
1451 // Test error handling reading built-in float type
1452 //
1453 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
1454 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1455   std::vector<double> seq;
1456   Input yin("---\n"
1457             "- 0.0\n"
1458             "- 1000.1\n"
1459             "- -123.456\n"
1460             "- 1.2.3\n"
1461             "...\n",
1462             /*Ctxt=*/NULL,
1463             suppressErrorMessages);
1464   yin >> seq;
1465
1466   EXPECT_TRUE(yin.error());
1467 }
1468
1469 //
1470 // Test error handling reading built-in Hex8 type
1471 //
1472 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
1473 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
1474   std::vector<Hex8> seq;
1475   Input yin("---\n"
1476             "- 0x12\n"
1477             "- 0xFE\n"
1478             "- 0x123\n"
1479             "...\n",
1480             /*Ctxt=*/NULL,
1481             suppressErrorMessages);
1482   yin >> seq;
1483
1484   EXPECT_TRUE(yin.error());
1485 }
1486
1487
1488 //
1489 // Test error handling reading built-in Hex16 type
1490 //
1491 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
1492 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
1493   std::vector<Hex16> seq;
1494   Input yin("---\n"
1495             "- 0x0012\n"
1496             "- 0xFEFF\n"
1497             "- 0x12345\n"
1498             "...\n",
1499             /*Ctxt=*/NULL,
1500             suppressErrorMessages);
1501   yin >> seq;
1502
1503   EXPECT_TRUE(yin.error());
1504 }
1505
1506 //
1507 // Test error handling reading built-in Hex32 type
1508 //
1509 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
1510 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
1511   std::vector<Hex32> seq;
1512   Input yin("---\n"
1513             "- 0x0012\n"
1514             "- 0xFEFF0000\n"
1515             "- 0x1234556789\n"
1516             "...\n",
1517             /*Ctxt=*/NULL,
1518             suppressErrorMessages);
1519   yin >> seq;
1520
1521   EXPECT_TRUE(yin.error());
1522 }
1523
1524 //
1525 // Test error handling reading built-in Hex64 type
1526 //
1527 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
1528 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
1529   std::vector<Hex64> seq;
1530   Input yin("---\n"
1531             "- 0x0012\n"
1532             "- 0xFFEEDDCCBBAA9988\n"
1533             "- 0x12345567890ABCDEF0\n"
1534             "...\n",
1535             /*Ctxt=*/NULL,
1536             suppressErrorMessages);
1537   yin >> seq;
1538
1539   EXPECT_TRUE(yin.error());
1540 }
1541
1542 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
1543   FooBar doc;
1544   {
1545     // We pass the suppressErrorMessages handler to handle the error
1546     // message generated in the constructor of Input.
1547     Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages);
1548     yin >> doc;
1549     EXPECT_TRUE(yin.error());
1550   }
1551
1552   {
1553     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages);
1554     yin >> doc;
1555     EXPECT_TRUE(yin.error());
1556   }
1557 }
1558
1559 struct OptionalTest {
1560   std::vector<int> Numbers;
1561 };
1562
1563 struct OptionalTestSeq {
1564   std::vector<OptionalTest> Tests;
1565 };
1566
1567 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
1568 namespace llvm {
1569 namespace yaml {
1570   template <>
1571   struct MappingTraits<OptionalTest> {
1572     static void mapping(IO& IO, OptionalTest &OT) {
1573       IO.mapOptional("Numbers", OT.Numbers);
1574     }
1575   };
1576
1577   template <>
1578   struct MappingTraits<OptionalTestSeq> {
1579     static void mapping(IO &IO, OptionalTestSeq &OTS) {
1580       IO.mapOptional("Tests", OTS.Tests);
1581     }
1582   };
1583 }
1584 }
1585
1586 TEST(YAMLIO, SequenceElideTest) {
1587   // Test that writing out a purely optional structure with its fields set to
1588   // default followed by other data is properly read back in.
1589   OptionalTestSeq Seq;
1590   OptionalTest One, Two, Three, Four;
1591   int N[] = {1, 2, 3};
1592   Three.Numbers.assign(N, N + 3);
1593   Seq.Tests.push_back(One);
1594   Seq.Tests.push_back(Two);
1595   Seq.Tests.push_back(Three);
1596   Seq.Tests.push_back(Four);
1597
1598   std::string intermediate;
1599   {
1600     llvm::raw_string_ostream ostr(intermediate);
1601     Output yout(ostr);
1602     yout << Seq;
1603   }
1604
1605   Input yin(intermediate);
1606   OptionalTestSeq Seq2;
1607   yin >> Seq2;
1608
1609   EXPECT_FALSE(yin.error());
1610
1611   EXPECT_EQ(4UL, Seq2.Tests.size());
1612
1613   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
1614   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
1615
1616   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
1617   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
1618   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
1619
1620   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
1621 }
1622
1623 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
1624   FooBar doc;
1625   Input yin("");
1626   yin >> doc;
1627   EXPECT_TRUE(yin.error());
1628 }
1629
1630 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
1631   OptionalTest doc;
1632   Input yin("");
1633   yin >> doc;
1634   EXPECT_FALSE(yin.error());
1635 }
1636
1637 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
1638   std::vector<uint8_t> seq;
1639   Input yin("", /*Ctxt=*/NULL, suppressErrorMessages);
1640   yin >> seq;
1641
1642   EXPECT_FALSE(yin.error());
1643   EXPECT_TRUE(seq.empty());
1644 }