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