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