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