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