Revert r237046. See the testcase on the thread where r237046 was committed.
[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 //  Test flow mapping
1372 //===----------------------------------------------------------------------===//
1373
1374 struct FlowFooBar {
1375   int foo;
1376   int bar;
1377
1378   FlowFooBar() : foo(0), bar(0) {}
1379   FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
1380 };
1381
1382 typedef std::vector<FlowFooBar> FlowFooBarSequence;
1383
1384 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
1385
1386 struct FlowFooBarDoc {
1387   FlowFooBar attribute;
1388   FlowFooBarSequence seq;
1389 };
1390
1391 namespace llvm {
1392 namespace yaml {
1393   template <>
1394   struct MappingTraits<FlowFooBar> {
1395     static void mapping(IO &io, FlowFooBar &fb) {
1396       io.mapRequired("foo", fb.foo);
1397       io.mapRequired("bar", fb.bar);
1398     }
1399
1400     static const bool flow = true;
1401   };
1402
1403   template <>
1404   struct MappingTraits<FlowFooBarDoc> {
1405     static void mapping(IO &io, FlowFooBarDoc &fb) {
1406       io.mapRequired("attribute", fb.attribute);
1407       io.mapRequired("seq", fb.seq);
1408     }
1409   };
1410 }
1411 }
1412
1413 //
1414 // Test writing then reading back custom mappings
1415 //
1416 TEST(YAMLIO, TestReadWriteMyFlowMapping) {
1417   std::string intermediate;
1418   {
1419     FlowFooBarDoc doc;
1420     doc.attribute = FlowFooBar(42, 907);
1421     doc.seq.push_back(FlowFooBar(1, 2));
1422     doc.seq.push_back(FlowFooBar(0, 0));
1423     doc.seq.push_back(FlowFooBar(-1, 1024));
1424
1425     llvm::raw_string_ostream ostr(intermediate);
1426     Output yout(ostr);
1427     yout << doc;
1428
1429     // Verify that mappings were written in flow style
1430     ostr.flush();
1431     llvm::StringRef flowOut(intermediate);
1432     EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
1433     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
1434     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
1435     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
1436   }
1437
1438   {
1439     Input yin(intermediate);
1440     FlowFooBarDoc doc2;
1441     yin >> doc2;
1442
1443     EXPECT_FALSE(yin.error());
1444     EXPECT_EQ(doc2.attribute.foo, 42);
1445     EXPECT_EQ(doc2.attribute.bar, 907);
1446     EXPECT_EQ(doc2.seq.size(), 3UL);
1447     EXPECT_EQ(doc2.seq[0].foo, 1);
1448     EXPECT_EQ(doc2.seq[0].bar, 2);
1449     EXPECT_EQ(doc2.seq[1].foo, 0);
1450     EXPECT_EQ(doc2.seq[1].bar, 0);
1451     EXPECT_EQ(doc2.seq[2].foo, -1);
1452     EXPECT_EQ(doc2.seq[2].bar, 1024);
1453   }
1454 }
1455
1456 //===----------------------------------------------------------------------===//
1457 //  Test error handling
1458 //===----------------------------------------------------------------------===//
1459
1460 //
1461 // Test error handling of unknown enumerated scalar
1462 //
1463 TEST(YAMLIO, TestColorsReadError) {
1464   ColorMap map;
1465   Input yin("---\n"
1466             "c1:  blue\n"
1467             "c2:  purple\n"
1468             "c3:  green\n"
1469             "...\n",
1470             /*Ctxt=*/nullptr,
1471             suppressErrorMessages);
1472   yin >> map;
1473   EXPECT_TRUE(!!yin.error());
1474 }
1475
1476
1477 //
1478 // Test error handling of flow sequence with unknown value
1479 //
1480 TEST(YAMLIO, TestFlagsReadError) {
1481   FlagsMap map;
1482   Input yin("---\n"
1483             "f1:  [ big ]\n"
1484             "f2:  [ round, hollow ]\n"
1485             "f3:  []\n"
1486             "...\n",
1487             /*Ctxt=*/nullptr,
1488             suppressErrorMessages);
1489   yin >> map;
1490
1491   EXPECT_TRUE(!!yin.error());
1492 }
1493
1494
1495 //
1496 // Test error handling reading built-in uint8_t type
1497 //
1498 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
1499 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1500   std::vector<uint8_t> seq;
1501   Input yin("---\n"
1502             "- 255\n"
1503             "- 0\n"
1504             "- 257\n"
1505             "...\n",
1506             /*Ctxt=*/nullptr,
1507             suppressErrorMessages);
1508   yin >> seq;
1509
1510   EXPECT_TRUE(!!yin.error());
1511 }
1512
1513
1514 //
1515 // Test error handling reading built-in uint16_t type
1516 //
1517 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
1518 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1519   std::vector<uint16_t> seq;
1520   Input yin("---\n"
1521             "- 65535\n"
1522             "- 0\n"
1523             "- 66000\n"
1524             "...\n",
1525             /*Ctxt=*/nullptr,
1526             suppressErrorMessages);
1527   yin >> seq;
1528
1529   EXPECT_TRUE(!!yin.error());
1530 }
1531
1532
1533 //
1534 // Test error handling reading built-in uint32_t type
1535 //
1536 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
1537 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1538   std::vector<uint32_t> seq;
1539   Input yin("---\n"
1540             "- 4000000000\n"
1541             "- 0\n"
1542             "- 5000000000\n"
1543             "...\n",
1544             /*Ctxt=*/nullptr,
1545             suppressErrorMessages);
1546   yin >> seq;
1547
1548   EXPECT_TRUE(!!yin.error());
1549 }
1550
1551
1552 //
1553 // Test error handling reading built-in uint64_t type
1554 //
1555 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
1556 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1557   std::vector<uint64_t> seq;
1558   Input yin("---\n"
1559             "- 18446744073709551615\n"
1560             "- 0\n"
1561             "- 19446744073709551615\n"
1562             "...\n",
1563             /*Ctxt=*/nullptr,
1564             suppressErrorMessages);
1565   yin >> seq;
1566
1567   EXPECT_TRUE(!!yin.error());
1568 }
1569
1570
1571 //
1572 // Test error handling reading built-in int8_t type
1573 //
1574 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
1575 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1576   std::vector<int8_t> seq;
1577   Input yin("---\n"
1578             "- -128\n"
1579             "- 0\n"
1580             "- 127\n"
1581             "- 128\n"
1582            "...\n",
1583             /*Ctxt=*/nullptr,
1584             suppressErrorMessages);
1585   yin >> seq;
1586
1587   EXPECT_TRUE(!!yin.error());
1588 }
1589
1590 //
1591 // Test error handling reading built-in int8_t type
1592 //
1593 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1594   std::vector<int8_t> seq;
1595   Input yin("---\n"
1596             "- -128\n"
1597             "- 0\n"
1598             "- 127\n"
1599             "- -129\n"
1600             "...\n",
1601             /*Ctxt=*/nullptr,
1602             suppressErrorMessages);
1603   yin >> seq;
1604
1605   EXPECT_TRUE(!!yin.error());
1606 }
1607
1608
1609 //
1610 // Test error handling reading built-in int16_t type
1611 //
1612 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
1613 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1614   std::vector<int16_t> seq;
1615   Input yin("---\n"
1616             "- 32767\n"
1617             "- 0\n"
1618             "- -32768\n"
1619             "- -32769\n"
1620             "...\n",
1621             /*Ctxt=*/nullptr,
1622             suppressErrorMessages);
1623   yin >> seq;
1624
1625   EXPECT_TRUE(!!yin.error());
1626 }
1627
1628
1629 //
1630 // Test error handling reading built-in int16_t type
1631 //
1632 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1633   std::vector<int16_t> seq;
1634   Input yin("---\n"
1635             "- 32767\n"
1636             "- 0\n"
1637             "- -32768\n"
1638             "- 32768\n"
1639             "...\n",
1640             /*Ctxt=*/nullptr,
1641             suppressErrorMessages);
1642   yin >> seq;
1643
1644   EXPECT_TRUE(!!yin.error());
1645 }
1646
1647
1648 //
1649 // Test error handling reading built-in int32_t type
1650 //
1651 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
1652 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1653   std::vector<int32_t> seq;
1654   Input yin("---\n"
1655             "- 2147483647\n"
1656             "- 0\n"
1657             "- -2147483648\n"
1658             "- -2147483649\n"
1659             "...\n",
1660             /*Ctxt=*/nullptr,
1661             suppressErrorMessages);
1662   yin >> seq;
1663
1664   EXPECT_TRUE(!!yin.error());
1665 }
1666
1667 //
1668 // Test error handling reading built-in int32_t type
1669 //
1670 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1671   std::vector<int32_t> seq;
1672   Input yin("---\n"
1673             "- 2147483647\n"
1674             "- 0\n"
1675             "- -2147483648\n"
1676             "- 2147483649\n"
1677             "...\n",
1678             /*Ctxt=*/nullptr,
1679             suppressErrorMessages);
1680   yin >> seq;
1681
1682   EXPECT_TRUE(!!yin.error());
1683 }
1684
1685
1686 //
1687 // Test error handling reading built-in int64_t type
1688 //
1689 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
1690 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1691   std::vector<int64_t> seq;
1692   Input yin("---\n"
1693             "- -9223372036854775808\n"
1694             "- 0\n"
1695             "- 9223372036854775807\n"
1696             "- -9223372036854775809\n"
1697             "...\n",
1698             /*Ctxt=*/nullptr,
1699             suppressErrorMessages);
1700   yin >> seq;
1701
1702   EXPECT_TRUE(!!yin.error());
1703 }
1704
1705 //
1706 // Test error handling reading built-in int64_t type
1707 //
1708 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1709   std::vector<int64_t> seq;
1710   Input yin("---\n"
1711             "- -9223372036854775808\n"
1712             "- 0\n"
1713             "- 9223372036854775807\n"
1714             "- 9223372036854775809\n"
1715             "...\n",
1716             /*Ctxt=*/nullptr,
1717             suppressErrorMessages);
1718   yin >> seq;
1719
1720   EXPECT_TRUE(!!yin.error());
1721 }
1722
1723 //
1724 // Test error handling reading built-in float type
1725 //
1726 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
1727 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1728   std::vector<float> seq;
1729   Input yin("---\n"
1730             "- 0.0\n"
1731             "- 1000.1\n"
1732             "- -123.456\n"
1733             "- 1.2.3\n"
1734             "...\n",
1735             /*Ctxt=*/nullptr,
1736             suppressErrorMessages);
1737   yin >> seq;
1738
1739   EXPECT_TRUE(!!yin.error());
1740 }
1741
1742 //
1743 // Test error handling reading built-in float type
1744 //
1745 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
1746 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1747   std::vector<double> seq;
1748   Input yin("---\n"
1749             "- 0.0\n"
1750             "- 1000.1\n"
1751             "- -123.456\n"
1752             "- 1.2.3\n"
1753             "...\n",
1754             /*Ctxt=*/nullptr,
1755             suppressErrorMessages);
1756   yin >> seq;
1757
1758   EXPECT_TRUE(!!yin.error());
1759 }
1760
1761 //
1762 // Test error handling reading built-in Hex8 type
1763 //
1764 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
1765 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
1766   std::vector<Hex8> seq;
1767   Input yin("---\n"
1768             "- 0x12\n"
1769             "- 0xFE\n"
1770             "- 0x123\n"
1771             "...\n",
1772             /*Ctxt=*/nullptr,
1773             suppressErrorMessages);
1774   yin >> seq;
1775
1776   EXPECT_TRUE(!!yin.error());
1777 }
1778
1779
1780 //
1781 // Test error handling reading built-in Hex16 type
1782 //
1783 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
1784 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
1785   std::vector<Hex16> seq;
1786   Input yin("---\n"
1787             "- 0x0012\n"
1788             "- 0xFEFF\n"
1789             "- 0x12345\n"
1790             "...\n",
1791             /*Ctxt=*/nullptr,
1792             suppressErrorMessages);
1793   yin >> seq;
1794
1795   EXPECT_TRUE(!!yin.error());
1796 }
1797
1798 //
1799 // Test error handling reading built-in Hex32 type
1800 //
1801 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
1802 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
1803   std::vector<Hex32> seq;
1804   Input yin("---\n"
1805             "- 0x0012\n"
1806             "- 0xFEFF0000\n"
1807             "- 0x1234556789\n"
1808             "...\n",
1809             /*Ctxt=*/nullptr,
1810             suppressErrorMessages);
1811   yin >> seq;
1812
1813   EXPECT_TRUE(!!yin.error());
1814 }
1815
1816 //
1817 // Test error handling reading built-in Hex64 type
1818 //
1819 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
1820 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
1821   std::vector<Hex64> seq;
1822   Input yin("---\n"
1823             "- 0x0012\n"
1824             "- 0xFFEEDDCCBBAA9988\n"
1825             "- 0x12345567890ABCDEF0\n"
1826             "...\n",
1827             /*Ctxt=*/nullptr,
1828             suppressErrorMessages);
1829   yin >> seq;
1830
1831   EXPECT_TRUE(!!yin.error());
1832 }
1833
1834 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
1835   FooBar doc;
1836   {
1837     // We pass the suppressErrorMessages handler to handle the error
1838     // message generated in the constructor of Input.
1839     Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
1840     yin >> doc;
1841     EXPECT_TRUE(!!yin.error());
1842   }
1843
1844   {
1845     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
1846     yin >> doc;
1847     EXPECT_TRUE(!!yin.error());
1848   }
1849 }
1850
1851 struct OptionalTest {
1852   std::vector<int> Numbers;
1853 };
1854
1855 struct OptionalTestSeq {
1856   std::vector<OptionalTest> Tests;
1857 };
1858
1859 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
1860 namespace llvm {
1861 namespace yaml {
1862   template <>
1863   struct MappingTraits<OptionalTest> {
1864     static void mapping(IO& IO, OptionalTest &OT) {
1865       IO.mapOptional("Numbers", OT.Numbers);
1866     }
1867   };
1868
1869   template <>
1870   struct MappingTraits<OptionalTestSeq> {
1871     static void mapping(IO &IO, OptionalTestSeq &OTS) {
1872       IO.mapOptional("Tests", OTS.Tests);
1873     }
1874   };
1875 }
1876 }
1877
1878 TEST(YAMLIO, SequenceElideTest) {
1879   // Test that writing out a purely optional structure with its fields set to
1880   // default followed by other data is properly read back in.
1881   OptionalTestSeq Seq;
1882   OptionalTest One, Two, Three, Four;
1883   int N[] = {1, 2, 3};
1884   Three.Numbers.assign(N, N + 3);
1885   Seq.Tests.push_back(One);
1886   Seq.Tests.push_back(Two);
1887   Seq.Tests.push_back(Three);
1888   Seq.Tests.push_back(Four);
1889
1890   std::string intermediate;
1891   {
1892     llvm::raw_string_ostream ostr(intermediate);
1893     Output yout(ostr);
1894     yout << Seq;
1895   }
1896
1897   Input yin(intermediate);
1898   OptionalTestSeq Seq2;
1899   yin >> Seq2;
1900
1901   EXPECT_FALSE(yin.error());
1902
1903   EXPECT_EQ(4UL, Seq2.Tests.size());
1904
1905   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
1906   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
1907
1908   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
1909   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
1910   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
1911
1912   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
1913 }
1914
1915 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
1916   FooBar doc;
1917   Input yin("");
1918   yin >> doc;
1919   EXPECT_TRUE(!!yin.error());
1920 }
1921
1922 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
1923   OptionalTest doc;
1924   Input yin("");
1925   yin >> doc;
1926   EXPECT_FALSE(yin.error());
1927 }
1928
1929 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
1930   std::vector<uint8_t> seq;
1931   Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
1932   yin >> seq;
1933
1934   EXPECT_FALSE(yin.error());
1935   EXPECT_TRUE(seq.empty());
1936 }