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