]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unittests/Support/YAMLIOTest.cpp
Vendor import of llvm trunk r321414:
[FreeBSD/FreeBSD.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/StringRef.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/Casting.h"
13 #include "llvm/Support/Endian.h"
14 #include "llvm/Support/Format.h"
15 #include "llvm/Support/YAMLTraits.h"
16 #include "gtest/gtest.h"
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 // Test YAML filename handling.
238 //
239 static void testErrorFilename(const llvm::SMDiagnostic &Error, void *) {
240   EXPECT_EQ(Error.getFilename(), "foo.yaml");
241 }
242
243 TEST(YAMLIO, TestGivenFilename) {
244   auto Buffer = llvm::MemoryBuffer::getMemBuffer("{ x: 42 }", "foo.yaml");
245   Input yin(*Buffer, nullptr, testErrorFilename);
246   FooBar Value;
247   yin >> Value;
248
249   EXPECT_TRUE(!!yin.error());
250 }
251
252
253 //===----------------------------------------------------------------------===//
254 //  Test built-in types
255 //===----------------------------------------------------------------------===//
256
257 struct BuiltInTypes {
258   llvm::StringRef str;
259   std::string stdstr;
260   uint64_t        u64;
261   uint32_t        u32;
262   uint16_t        u16;
263   uint8_t         u8;
264   bool            b;
265   int64_t         s64;
266   int32_t         s32;
267   int16_t         s16;
268   int8_t          s8;
269   float           f;
270   double          d;
271   Hex8            h8;
272   Hex16           h16;
273   Hex32           h32;
274   Hex64           h64;
275 };
276
277 namespace llvm {
278 namespace yaml {
279   template <>
280   struct MappingTraits<BuiltInTypes> {
281     static void mapping(IO &io, BuiltInTypes& bt) {
282       io.mapRequired("str",      bt.str);
283       io.mapRequired("stdstr",   bt.stdstr);
284       io.mapRequired("u64",      bt.u64);
285       io.mapRequired("u32",      bt.u32);
286       io.mapRequired("u16",      bt.u16);
287       io.mapRequired("u8",       bt.u8);
288       io.mapRequired("b",        bt.b);
289       io.mapRequired("s64",      bt.s64);
290       io.mapRequired("s32",      bt.s32);
291       io.mapRequired("s16",      bt.s16);
292       io.mapRequired("s8",       bt.s8);
293       io.mapRequired("f",        bt.f);
294       io.mapRequired("d",        bt.d);
295       io.mapRequired("h8",       bt.h8);
296       io.mapRequired("h16",      bt.h16);
297       io.mapRequired("h32",      bt.h32);
298       io.mapRequired("h64",      bt.h64);
299     }
300   };
301 }
302 }
303
304
305 //
306 // Test the reading of all built-in scalar conversions
307 //
308 TEST(YAMLIO, TestReadBuiltInTypes) {
309   BuiltInTypes map;
310   Input yin("---\n"
311             "str:      hello there\n"
312             "stdstr:   hello where?\n"
313             "u64:      5000000000\n"
314             "u32:      4000000000\n"
315             "u16:      65000\n"
316             "u8:       255\n"
317             "b:        false\n"
318             "s64:      -5000000000\n"
319             "s32:      -2000000000\n"
320             "s16:      -32000\n"
321             "s8:       -127\n"
322             "f:        137.125\n"
323             "d:        -2.8625\n"
324             "h8:       0xFF\n"
325             "h16:      0x8765\n"
326             "h32:      0xFEDCBA98\n"
327             "h64:      0xFEDCBA9876543210\n"
328            "...\n");
329   yin >> map;
330
331   EXPECT_FALSE(yin.error());
332   EXPECT_TRUE(map.str.equals("hello there"));
333   EXPECT_TRUE(map.stdstr == "hello where?");
334   EXPECT_EQ(map.u64, 5000000000ULL);
335   EXPECT_EQ(map.u32, 4000000000U);
336   EXPECT_EQ(map.u16, 65000);
337   EXPECT_EQ(map.u8,  255);
338   EXPECT_EQ(map.b,   false);
339   EXPECT_EQ(map.s64, -5000000000LL);
340   EXPECT_EQ(map.s32, -2000000000L);
341   EXPECT_EQ(map.s16, -32000);
342   EXPECT_EQ(map.s8,  -127);
343   EXPECT_EQ(map.f,   137.125);
344   EXPECT_EQ(map.d,   -2.8625);
345   EXPECT_EQ(map.h8,  Hex8(255));
346   EXPECT_EQ(map.h16, Hex16(0x8765));
347   EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
348   EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
349 }
350
351
352 //
353 // Test writing then reading back all built-in scalar types
354 //
355 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
356   std::string intermediate;
357   {
358     BuiltInTypes map;
359     map.str = "one two";
360     map.stdstr = "three four";
361     map.u64 = 6000000000ULL;
362     map.u32 = 3000000000U;
363     map.u16 = 50000;
364     map.u8  = 254;
365     map.b   = true;
366     map.s64 = -6000000000LL;
367     map.s32 = -2000000000;
368     map.s16 = -32000;
369     map.s8  = -128;
370     map.f   = 3.25;
371     map.d   = -2.8625;
372     map.h8  = 254;
373     map.h16 = 50000;
374     map.h32 = 3000000000U;
375     map.h64 = 6000000000LL;
376
377     llvm::raw_string_ostream ostr(intermediate);
378     Output yout(ostr);
379     yout << map;
380   }
381
382   {
383     Input yin(intermediate);
384     BuiltInTypes map;
385     yin >> map;
386
387     EXPECT_FALSE(yin.error());
388     EXPECT_TRUE(map.str.equals("one two"));
389     EXPECT_TRUE(map.stdstr == "three four");
390     EXPECT_EQ(map.u64,      6000000000ULL);
391     EXPECT_EQ(map.u32,      3000000000U);
392     EXPECT_EQ(map.u16,      50000);
393     EXPECT_EQ(map.u8,       254);
394     EXPECT_EQ(map.b,        true);
395     EXPECT_EQ(map.s64,      -6000000000LL);
396     EXPECT_EQ(map.s32,      -2000000000L);
397     EXPECT_EQ(map.s16,      -32000);
398     EXPECT_EQ(map.s8,       -128);
399     EXPECT_EQ(map.f,        3.25);
400     EXPECT_EQ(map.d,        -2.8625);
401     EXPECT_EQ(map.h8,       Hex8(254));
402     EXPECT_EQ(map.h16,      Hex16(50000));
403     EXPECT_EQ(map.h32,      Hex32(3000000000U));
404     EXPECT_EQ(map.h64,      Hex64(6000000000LL));
405   }
406 }
407
408 //===----------------------------------------------------------------------===//
409 //  Test endian-aware types
410 //===----------------------------------------------------------------------===//
411
412 struct EndianTypes {
413   typedef llvm::support::detail::packed_endian_specific_integral<
414       float, llvm::support::little, llvm::support::unaligned>
415       ulittle_float;
416   typedef llvm::support::detail::packed_endian_specific_integral<
417       double, llvm::support::little, llvm::support::unaligned>
418       ulittle_double;
419
420   llvm::support::ulittle64_t u64;
421   llvm::support::ulittle32_t u32;
422   llvm::support::ulittle16_t u16;
423   llvm::support::little64_t s64;
424   llvm::support::little32_t s32;
425   llvm::support::little16_t s16;
426   ulittle_float f;
427   ulittle_double d;
428 };
429
430 namespace llvm {
431 namespace yaml {
432 template <> struct MappingTraits<EndianTypes> {
433   static void mapping(IO &io, EndianTypes &et) {
434     io.mapRequired("u64", et.u64);
435     io.mapRequired("u32", et.u32);
436     io.mapRequired("u16", et.u16);
437     io.mapRequired("s64", et.s64);
438     io.mapRequired("s32", et.s32);
439     io.mapRequired("s16", et.s16);
440     io.mapRequired("f", et.f);
441     io.mapRequired("d", et.d);
442   }
443 };
444 }
445 }
446
447 //
448 // Test the reading of all endian scalar conversions
449 //
450 TEST(YAMLIO, TestReadEndianTypes) {
451   EndianTypes map;
452   Input yin("---\n"
453             "u64:      5000000000\n"
454             "u32:      4000000000\n"
455             "u16:      65000\n"
456             "s64:      -5000000000\n"
457             "s32:      -2000000000\n"
458             "s16:      -32000\n"
459             "f:        3.25\n"
460             "d:        -2.8625\n"
461             "...\n");
462   yin >> map;
463
464   EXPECT_FALSE(yin.error());
465   EXPECT_EQ(map.u64, 5000000000ULL);
466   EXPECT_EQ(map.u32, 4000000000U);
467   EXPECT_EQ(map.u16, 65000);
468   EXPECT_EQ(map.s64, -5000000000LL);
469   EXPECT_EQ(map.s32, -2000000000L);
470   EXPECT_EQ(map.s16, -32000);
471   EXPECT_EQ(map.f, 3.25f);
472   EXPECT_EQ(map.d, -2.8625);
473 }
474
475 //
476 // Test writing then reading back all endian-aware scalar types
477 //
478 TEST(YAMLIO, TestReadWriteEndianTypes) {
479   std::string intermediate;
480   {
481     EndianTypes map;
482     map.u64 = 6000000000ULL;
483     map.u32 = 3000000000U;
484     map.u16 = 50000;
485     map.s64 = -6000000000LL;
486     map.s32 = -2000000000;
487     map.s16 = -32000;
488     map.f = 3.25f;
489     map.d = -2.8625;
490
491     llvm::raw_string_ostream ostr(intermediate);
492     Output yout(ostr);
493     yout << map;
494   }
495
496   {
497     Input yin(intermediate);
498     EndianTypes map;
499     yin >> map;
500
501     EXPECT_FALSE(yin.error());
502     EXPECT_EQ(map.u64, 6000000000ULL);
503     EXPECT_EQ(map.u32, 3000000000U);
504     EXPECT_EQ(map.u16, 50000);
505     EXPECT_EQ(map.s64, -6000000000LL);
506     EXPECT_EQ(map.s32, -2000000000L);
507     EXPECT_EQ(map.s16, -32000);
508     EXPECT_EQ(map.f, 3.25f);
509     EXPECT_EQ(map.d, -2.8625);
510   }
511 }
512
513 struct StringTypes {
514   llvm::StringRef str1;
515   llvm::StringRef str2;
516   llvm::StringRef str3;
517   llvm::StringRef str4;
518   llvm::StringRef str5;
519   llvm::StringRef str6;
520   llvm::StringRef str7;
521   llvm::StringRef str8;
522   llvm::StringRef str9;
523   llvm::StringRef str10;
524   llvm::StringRef str11;
525   std::string stdstr1;
526   std::string stdstr2;
527   std::string stdstr3;
528   std::string stdstr4;
529   std::string stdstr5;
530   std::string stdstr6;
531   std::string stdstr7;
532   std::string stdstr8;
533   std::string stdstr9;
534   std::string stdstr10;
535   std::string stdstr11;
536 };
537
538 namespace llvm {
539 namespace yaml {
540   template <>
541   struct MappingTraits<StringTypes> {
542     static void mapping(IO &io, StringTypes& st) {
543       io.mapRequired("str1",      st.str1);
544       io.mapRequired("str2",      st.str2);
545       io.mapRequired("str3",      st.str3);
546       io.mapRequired("str4",      st.str4);
547       io.mapRequired("str5",      st.str5);
548       io.mapRequired("str6",      st.str6);
549       io.mapRequired("str7",      st.str7);
550       io.mapRequired("str8",      st.str8);
551       io.mapRequired("str9",      st.str9);
552       io.mapRequired("str10",     st.str10);
553       io.mapRequired("str11",     st.str11);
554       io.mapRequired("stdstr1",   st.stdstr1);
555       io.mapRequired("stdstr2",   st.stdstr2);
556       io.mapRequired("stdstr3",   st.stdstr3);
557       io.mapRequired("stdstr4",   st.stdstr4);
558       io.mapRequired("stdstr5",   st.stdstr5);
559       io.mapRequired("stdstr6",   st.stdstr6);
560       io.mapRequired("stdstr7",   st.stdstr7);
561       io.mapRequired("stdstr8",   st.stdstr8);
562       io.mapRequired("stdstr9",   st.stdstr9);
563       io.mapRequired("stdstr10",  st.stdstr10);
564       io.mapRequired("stdstr11",  st.stdstr11);
565     }
566   };
567 }
568 }
569
570 TEST(YAMLIO, TestReadWriteStringTypes) {
571   std::string intermediate;
572   {
573     StringTypes map;
574     map.str1 = "'aaa";
575     map.str2 = "\"bbb";
576     map.str3 = "`ccc";
577     map.str4 = "@ddd";
578     map.str5 = "";
579     map.str6 = "0000000004000000";
580     map.str7 = "true";
581     map.str8 = "FALSE";
582     map.str9 = "~";
583     map.str10 = "0.2e20";
584     map.str11 = "0x30";
585     map.stdstr1 = "'eee";
586     map.stdstr2 = "\"fff";
587     map.stdstr3 = "`ggg";
588     map.stdstr4 = "@hhh";
589     map.stdstr5 = "";
590     map.stdstr6 = "0000000004000000";
591     map.stdstr7 = "true";
592     map.stdstr8 = "FALSE";
593     map.stdstr9 = "~";
594     map.stdstr10 = "0.2e20";
595     map.stdstr11 = "0x30";
596
597     llvm::raw_string_ostream ostr(intermediate);
598     Output yout(ostr);
599     yout << map;
600   }
601
602   llvm::StringRef flowOut(intermediate);
603   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
604   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
605   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
606   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
607   EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
608   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
609   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
610   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
611   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
612   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
613   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
614   EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
615   EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
616   EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
617   EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
618   EXPECT_NE(std::string::npos, flowOut.find("''\n"));
619   EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
620
621   {
622     Input yin(intermediate);
623     StringTypes map;
624     yin >> map;
625
626     EXPECT_FALSE(yin.error());
627     EXPECT_TRUE(map.str1.equals("'aaa"));
628     EXPECT_TRUE(map.str2.equals("\"bbb"));
629     EXPECT_TRUE(map.str3.equals("`ccc"));
630     EXPECT_TRUE(map.str4.equals("@ddd"));
631     EXPECT_TRUE(map.str5.equals(""));
632     EXPECT_TRUE(map.str6.equals("0000000004000000"));
633     EXPECT_TRUE(map.stdstr1 == "'eee");
634     EXPECT_TRUE(map.stdstr2 == "\"fff");
635     EXPECT_TRUE(map.stdstr3 == "`ggg");
636     EXPECT_TRUE(map.stdstr4 == "@hhh");
637     EXPECT_TRUE(map.stdstr5 == "");
638     EXPECT_TRUE(map.stdstr6 == "0000000004000000");
639   }
640 }
641
642 //===----------------------------------------------------------------------===//
643 //  Test ScalarEnumerationTraits
644 //===----------------------------------------------------------------------===//
645
646 enum Colors {
647     cRed,
648     cBlue,
649     cGreen,
650     cYellow
651 };
652
653 struct ColorMap {
654   Colors      c1;
655   Colors      c2;
656   Colors      c3;
657   Colors      c4;
658   Colors      c5;
659   Colors      c6;
660 };
661
662 namespace llvm {
663 namespace yaml {
664   template <>
665   struct ScalarEnumerationTraits<Colors> {
666     static void enumeration(IO &io, Colors &value) {
667       io.enumCase(value, "red",   cRed);
668       io.enumCase(value, "blue",  cBlue);
669       io.enumCase(value, "green", cGreen);
670       io.enumCase(value, "yellow",cYellow);
671     }
672   };
673   template <>
674   struct MappingTraits<ColorMap> {
675     static void mapping(IO &io, ColorMap& c) {
676       io.mapRequired("c1", c.c1);
677       io.mapRequired("c2", c.c2);
678       io.mapRequired("c3", c.c3);
679       io.mapOptional("c4", c.c4, cBlue);   // supplies default
680       io.mapOptional("c5", c.c5, cYellow); // supplies default
681       io.mapOptional("c6", c.c6, cRed);    // supplies default
682     }
683   };
684 }
685 }
686
687
688 //
689 // Test reading enumerated scalars
690 //
691 TEST(YAMLIO, TestEnumRead) {
692   ColorMap map;
693   Input yin("---\n"
694             "c1:  blue\n"
695             "c2:  red\n"
696             "c3:  green\n"
697             "c5:  yellow\n"
698             "...\n");
699   yin >> map;
700
701   EXPECT_FALSE(yin.error());
702   EXPECT_EQ(cBlue,  map.c1);
703   EXPECT_EQ(cRed,   map.c2);
704   EXPECT_EQ(cGreen, map.c3);
705   EXPECT_EQ(cBlue,  map.c4);  // tests default
706   EXPECT_EQ(cYellow,map.c5);  // tests overridden
707   EXPECT_EQ(cRed,   map.c6);  // tests default
708 }
709
710
711
712 //===----------------------------------------------------------------------===//
713 //  Test ScalarBitSetTraits
714 //===----------------------------------------------------------------------===//
715
716 enum MyFlags {
717   flagNone    = 0,
718   flagBig     = 1 << 0,
719   flagFlat    = 1 << 1,
720   flagRound   = 1 << 2,
721   flagPointy  = 1 << 3
722 };
723 inline MyFlags operator|(MyFlags a, MyFlags b) {
724   return static_cast<MyFlags>(
725                       static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
726 }
727
728 struct FlagsMap {
729   MyFlags     f1;
730   MyFlags     f2;
731   MyFlags     f3;
732   MyFlags     f4;
733 };
734
735
736 namespace llvm {
737 namespace yaml {
738   template <>
739   struct ScalarBitSetTraits<MyFlags> {
740     static void bitset(IO &io, MyFlags &value) {
741       io.bitSetCase(value, "big",   flagBig);
742       io.bitSetCase(value, "flat",  flagFlat);
743       io.bitSetCase(value, "round", flagRound);
744       io.bitSetCase(value, "pointy",flagPointy);
745     }
746   };
747   template <>
748   struct MappingTraits<FlagsMap> {
749     static void mapping(IO &io, FlagsMap& c) {
750       io.mapRequired("f1", c.f1);
751       io.mapRequired("f2", c.f2);
752       io.mapRequired("f3", c.f3);
753       io.mapOptional("f4", c.f4, MyFlags(flagRound));
754      }
755   };
756 }
757 }
758
759
760 //
761 // Test reading flow sequence representing bit-mask values
762 //
763 TEST(YAMLIO, TestFlagsRead) {
764   FlagsMap map;
765   Input yin("---\n"
766             "f1:  [ big ]\n"
767             "f2:  [ round, flat ]\n"
768             "f3:  []\n"
769             "...\n");
770   yin >> map;
771
772   EXPECT_FALSE(yin.error());
773   EXPECT_EQ(flagBig,              map.f1);
774   EXPECT_EQ(flagRound|flagFlat,   map.f2);
775   EXPECT_EQ(flagNone,             map.f3);  // check empty set
776   EXPECT_EQ(flagRound,            map.f4);  // check optional key
777 }
778
779
780 //
781 // Test writing then reading back bit-mask values
782 //
783 TEST(YAMLIO, TestReadWriteFlags) {
784   std::string intermediate;
785   {
786     FlagsMap map;
787     map.f1 = flagBig;
788     map.f2 = flagRound | flagFlat;
789     map.f3 = flagNone;
790     map.f4 = flagNone;
791
792     llvm::raw_string_ostream ostr(intermediate);
793     Output yout(ostr);
794     yout << map;
795   }
796
797   {
798     Input yin(intermediate);
799     FlagsMap map2;
800     yin >> map2;
801
802     EXPECT_FALSE(yin.error());
803     EXPECT_EQ(flagBig,              map2.f1);
804     EXPECT_EQ(flagRound|flagFlat,   map2.f2);
805     EXPECT_EQ(flagNone,             map2.f3);
806     //EXPECT_EQ(flagRound,            map2.f4);  // check optional key
807   }
808 }
809
810
811
812 //===----------------------------------------------------------------------===//
813 //  Test ScalarTraits
814 //===----------------------------------------------------------------------===//
815
816 struct MyCustomType {
817   int length;
818   int width;
819 };
820
821 struct MyCustomTypeMap {
822   MyCustomType     f1;
823   MyCustomType     f2;
824   int              f3;
825 };
826
827
828 namespace llvm {
829 namespace yaml {
830   template <>
831   struct MappingTraits<MyCustomTypeMap> {
832     static void mapping(IO &io, MyCustomTypeMap& s) {
833       io.mapRequired("f1", s.f1);
834       io.mapRequired("f2", s.f2);
835       io.mapRequired("f3", s.f3);
836      }
837   };
838   // MyCustomType is formatted as a yaml scalar.  A value of
839   // {length=3, width=4} would be represented in yaml as "3 by 4".
840   template<>
841   struct ScalarTraits<MyCustomType> {
842     static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
843       out << llvm::format("%d by %d", value.length, value.width);
844     }
845     static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
846       size_t byStart = scalar.find("by");
847       if ( byStart != StringRef::npos ) {
848         StringRef lenStr = scalar.slice(0, byStart);
849         lenStr = lenStr.rtrim();
850         if ( lenStr.getAsInteger(0, value.length) ) {
851           return "malformed length";
852         }
853         StringRef widthStr = scalar.drop_front(byStart+2);
854         widthStr = widthStr.ltrim();
855         if ( widthStr.getAsInteger(0, value.width) ) {
856           return "malformed width";
857         }
858         return StringRef();
859       }
860       else {
861           return "malformed by";
862       }
863     }
864     static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
865   };
866 }
867 }
868
869
870 //
871 // Test writing then reading back custom values
872 //
873 TEST(YAMLIO, TestReadWriteMyCustomType) {
874   std::string intermediate;
875   {
876     MyCustomTypeMap map;
877     map.f1.length = 1;
878     map.f1.width  = 4;
879     map.f2.length = 100;
880     map.f2.width  = 400;
881     map.f3 = 10;
882
883     llvm::raw_string_ostream ostr(intermediate);
884     Output yout(ostr);
885     yout << map;
886   }
887
888   {
889     Input yin(intermediate);
890     MyCustomTypeMap map2;
891     yin >> map2;
892
893     EXPECT_FALSE(yin.error());
894     EXPECT_EQ(1,      map2.f1.length);
895     EXPECT_EQ(4,      map2.f1.width);
896     EXPECT_EQ(100,    map2.f2.length);
897     EXPECT_EQ(400,    map2.f2.width);
898     EXPECT_EQ(10,     map2.f3);
899   }
900 }
901
902
903 //===----------------------------------------------------------------------===//
904 //  Test BlockScalarTraits
905 //===----------------------------------------------------------------------===//
906
907 struct MultilineStringType {
908   std::string str;
909 };
910
911 struct MultilineStringTypeMap {
912   MultilineStringType name;
913   MultilineStringType description;
914   MultilineStringType ingredients;
915   MultilineStringType recipes;
916   MultilineStringType warningLabels;
917   MultilineStringType documentation;
918   int price;
919 };
920
921 namespace llvm {
922 namespace yaml {
923   template <>
924   struct MappingTraits<MultilineStringTypeMap> {
925     static void mapping(IO &io, MultilineStringTypeMap& s) {
926       io.mapRequired("name", s.name);
927       io.mapRequired("description", s.description);
928       io.mapRequired("ingredients", s.ingredients);
929       io.mapRequired("recipes", s.recipes);
930       io.mapRequired("warningLabels", s.warningLabels);
931       io.mapRequired("documentation", s.documentation);
932       io.mapRequired("price", s.price);
933      }
934   };
935
936   // MultilineStringType is formatted as a yaml block literal scalar. A value of
937   // "Hello\nWorld" would be represented in yaml as
938   //  |
939   //    Hello
940   //    World
941   template <>
942   struct BlockScalarTraits<MultilineStringType> {
943     static void output(const MultilineStringType &value, void *ctxt,
944                        llvm::raw_ostream &out) {
945       out << value.str;
946     }
947     static StringRef input(StringRef scalar, void *ctxt,
948                            MultilineStringType &value) {
949       value.str = scalar.str();
950       return StringRef();
951     }
952   };
953 }
954 }
955
956 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
957
958 //
959 // Test writing then reading back custom values
960 //
961 TEST(YAMLIO, TestReadWriteMultilineStringType) {
962   std::string intermediate;
963   {
964     MultilineStringTypeMap map;
965     map.name.str = "An Item";
966     map.description.str = "Hello\nWorld";
967     map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n";
968     map.recipes.str = "\n\nTest 1\n\n\n";
969     map.warningLabels.str = "";
970     map.documentation.str = "\n\n";
971     map.price = 350;
972
973     llvm::raw_string_ostream ostr(intermediate);
974     Output yout(ostr);
975     yout << map;
976   }
977   {
978     Input yin(intermediate);
979     MultilineStringTypeMap map2;
980     yin >> map2;
981
982     EXPECT_FALSE(yin.error());
983     EXPECT_EQ(map2.name.str, "An Item\n");
984     EXPECT_EQ(map2.description.str, "Hello\nWorld\n");
985     EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n");
986     EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n");
987     EXPECT_TRUE(map2.warningLabels.str.empty());
988     EXPECT_TRUE(map2.documentation.str.empty());
989     EXPECT_EQ(map2.price, 350);
990   }
991 }
992
993 //
994 // Test writing then reading back custom values
995 //
996 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
997   std::string intermediate;
998   {
999     std::vector<MultilineStringType> documents;
1000     MultilineStringType doc;
1001     doc.str = "Hello\nWorld";
1002     documents.push_back(doc);
1003
1004     llvm::raw_string_ostream ostr(intermediate);
1005     Output yout(ostr);
1006     yout << documents;
1007
1008     // Verify that the block scalar header was written out on the same line
1009     // as the document marker.
1010     EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |"));
1011   }
1012   {
1013     Input yin(intermediate);
1014     std::vector<MultilineStringType> documents2;
1015     yin >> documents2;
1016
1017     EXPECT_FALSE(yin.error());
1018     EXPECT_EQ(documents2.size(), size_t(1));
1019     EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
1020   }
1021 }
1022
1023 TEST(YAMLIO, TestReadWriteBlockScalarValue) {
1024   std::string intermediate;
1025   {
1026     MultilineStringType doc;
1027     doc.str = "Just a block\nscalar doc";
1028
1029     llvm::raw_string_ostream ostr(intermediate);
1030     Output yout(ostr);
1031     yout << doc;
1032   }
1033   {
1034     Input yin(intermediate);
1035     MultilineStringType doc;
1036     yin >> doc;
1037
1038     EXPECT_FALSE(yin.error());
1039     EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
1040   }
1041 }
1042
1043 //===----------------------------------------------------------------------===//
1044 //  Test flow sequences
1045 //===----------------------------------------------------------------------===//
1046
1047 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
1048 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
1049 LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, MyString)
1050 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyString)
1051
1052 namespace llvm {
1053 namespace yaml {
1054   template<>
1055   struct ScalarTraits<MyNumber> {
1056     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
1057       out << value;
1058     }
1059
1060     static StringRef input(StringRef scalar, void *, MyNumber &value) {
1061       long long n;
1062       if ( getAsSignedInteger(scalar, 0, n) )
1063         return "invalid number";
1064       value = n;
1065       return StringRef();
1066     }
1067
1068     static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1069   };
1070
1071   template <> struct ScalarTraits<MyString> {
1072     using Impl = ScalarTraits<StringRef>;
1073     static void output(const MyString &V, void *Ctx, raw_ostream &OS) {
1074       Impl::output(V, Ctx, OS);
1075     }
1076     static StringRef input(StringRef S, void *Ctx, MyString &V) {
1077       return Impl::input(S, Ctx, V.value);
1078     }
1079     static QuotingType mustQuote(StringRef S) {
1080       return Impl::mustQuote(S);
1081     }
1082   };
1083 }
1084 }
1085
1086 struct NameAndNumbers {
1087   llvm::StringRef               name;
1088   std::vector<MyString>         strings;
1089   std::vector<MyNumber>         single;
1090   std::vector<MyNumber>         numbers;
1091 };
1092
1093 namespace llvm {
1094 namespace yaml {
1095   template <>
1096   struct MappingTraits<NameAndNumbers> {
1097     static void mapping(IO &io, NameAndNumbers& nn) {
1098       io.mapRequired("name",     nn.name);
1099       io.mapRequired("strings",  nn.strings);
1100       io.mapRequired("single",   nn.single);
1101       io.mapRequired("numbers",  nn.numbers);
1102     }
1103   };
1104 }
1105 }
1106
1107 typedef std::vector<MyNumber> MyNumberFlowSequence;
1108
1109 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
1110
1111 struct NameAndNumbersFlow {
1112   llvm::StringRef                    name;
1113   std::vector<MyNumberFlowSequence>  sequenceOfNumbers;
1114 };
1115
1116 namespace llvm {
1117 namespace yaml {
1118   template <>
1119   struct MappingTraits<NameAndNumbersFlow> {
1120     static void mapping(IO &io, NameAndNumbersFlow& nn) {
1121       io.mapRequired("name",     nn.name);
1122       io.mapRequired("sequenceOfNumbers",  nn.sequenceOfNumbers);
1123     }
1124   };
1125 }
1126 }
1127
1128 //
1129 // Test writing then reading back custom values
1130 //
1131 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
1132   std::string intermediate;
1133   {
1134     NameAndNumbers map;
1135     map.name  = "hello";
1136     map.strings.push_back(llvm::StringRef("one"));
1137     map.strings.push_back(llvm::StringRef("two"));
1138     map.single.push_back(1);
1139     map.numbers.push_back(10);
1140     map.numbers.push_back(-30);
1141     map.numbers.push_back(1024);
1142
1143     llvm::raw_string_ostream ostr(intermediate);
1144     Output yout(ostr);
1145     yout << map;
1146
1147     // Verify sequences were written in flow style
1148     ostr.flush();
1149     llvm::StringRef flowOut(intermediate);
1150     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
1151     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
1152   }
1153
1154   {
1155     Input yin(intermediate);
1156     NameAndNumbers map2;
1157     yin >> map2;
1158
1159     EXPECT_FALSE(yin.error());
1160     EXPECT_TRUE(map2.name.equals("hello"));
1161     EXPECT_EQ(map2.strings.size(), 2UL);
1162     EXPECT_TRUE(map2.strings[0].value.equals("one"));
1163     EXPECT_TRUE(map2.strings[1].value.equals("two"));
1164     EXPECT_EQ(map2.single.size(), 1UL);
1165     EXPECT_EQ(1,       map2.single[0]);
1166     EXPECT_EQ(map2.numbers.size(), 3UL);
1167     EXPECT_EQ(10,      map2.numbers[0]);
1168     EXPECT_EQ(-30,     map2.numbers[1]);
1169     EXPECT_EQ(1024,    map2.numbers[2]);
1170   }
1171 }
1172
1173
1174 //
1175 // Test writing then reading back a sequence of flow sequences.
1176 //
1177 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
1178   std::string intermediate;
1179   {
1180     NameAndNumbersFlow map;
1181     map.name  = "hello";
1182     MyNumberFlowSequence single = { 0 };
1183     MyNumberFlowSequence numbers = { 12, 1, -512 };
1184     map.sequenceOfNumbers.push_back(single);
1185     map.sequenceOfNumbers.push_back(numbers);
1186     map.sequenceOfNumbers.push_back(MyNumberFlowSequence());
1187
1188     llvm::raw_string_ostream ostr(intermediate);
1189     Output yout(ostr);
1190     yout << map;
1191
1192     // Verify sequences were written in flow style
1193     // and that the parent sequence used '-'.
1194     ostr.flush();
1195     llvm::StringRef flowOut(intermediate);
1196     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]"));
1197     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]"));
1198     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [  ]"));
1199   }
1200
1201   {
1202     Input yin(intermediate);
1203     NameAndNumbersFlow map2;
1204     yin >> map2;
1205
1206     EXPECT_FALSE(yin.error());
1207     EXPECT_TRUE(map2.name.equals("hello"));
1208     EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL);
1209     EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL);
1210     EXPECT_EQ(0,    map2.sequenceOfNumbers[0][0]);
1211     EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL);
1212     EXPECT_EQ(12,   map2.sequenceOfNumbers[1][0]);
1213     EXPECT_EQ(1,    map2.sequenceOfNumbers[1][1]);
1214     EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]);
1215     EXPECT_TRUE(map2.sequenceOfNumbers[2].empty());
1216   }
1217 }
1218
1219 //===----------------------------------------------------------------------===//
1220 //  Test normalizing/denormalizing
1221 //===----------------------------------------------------------------------===//
1222
1223 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
1224
1225 typedef std::vector<TotalSeconds> SecondsSequence;
1226
1227 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
1228
1229
1230 namespace llvm {
1231 namespace yaml {
1232   template <>
1233   struct MappingTraits<TotalSeconds> {
1234
1235     class NormalizedSeconds {
1236     public:
1237       NormalizedSeconds(IO &io)
1238         : hours(0), minutes(0), seconds(0) {
1239       }
1240       NormalizedSeconds(IO &, TotalSeconds &secs)
1241         : hours(secs/3600),
1242           minutes((secs - (hours*3600))/60),
1243           seconds(secs % 60) {
1244       }
1245       TotalSeconds denormalize(IO &) {
1246         return TotalSeconds(hours*3600 + minutes*60 + seconds);
1247       }
1248
1249       uint32_t     hours;
1250       uint8_t      minutes;
1251       uint8_t      seconds;
1252     };
1253
1254     static void mapping(IO &io, TotalSeconds &secs) {
1255       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
1256
1257       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
1258       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
1259       io.mapRequired("seconds",  keys->seconds);
1260     }
1261   };
1262 }
1263 }
1264
1265
1266 //
1267 // Test the reading of a yaml sequence of mappings
1268 //
1269 TEST(YAMLIO, TestReadMySecondsSequence) {
1270   SecondsSequence seq;
1271   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
1272   yin >> seq;
1273
1274   EXPECT_FALSE(yin.error());
1275   EXPECT_EQ(seq.size(), 2UL);
1276   EXPECT_EQ(seq[0], 3605U);
1277   EXPECT_EQ(seq[1], 59U);
1278 }
1279
1280
1281 //
1282 // Test writing then reading back custom values
1283 //
1284 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
1285   std::string intermediate;
1286   {
1287     SecondsSequence seq;
1288     seq.push_back(4000);
1289     seq.push_back(500);
1290     seq.push_back(59);
1291
1292     llvm::raw_string_ostream ostr(intermediate);
1293     Output yout(ostr);
1294     yout << seq;
1295   }
1296   {
1297     Input yin(intermediate);
1298     SecondsSequence seq2;
1299     yin >> seq2;
1300
1301     EXPECT_FALSE(yin.error());
1302     EXPECT_EQ(seq2.size(), 3UL);
1303     EXPECT_EQ(seq2[0], 4000U);
1304     EXPECT_EQ(seq2[1], 500U);
1305     EXPECT_EQ(seq2[2], 59U);
1306   }
1307 }
1308
1309
1310 //===----------------------------------------------------------------------===//
1311 //  Test dynamic typing
1312 //===----------------------------------------------------------------------===//
1313
1314 enum AFlags {
1315     a1,
1316     a2,
1317     a3
1318 };
1319
1320 enum BFlags {
1321     b1,
1322     b2,
1323     b3
1324 };
1325
1326 enum Kind {
1327     kindA,
1328     kindB
1329 };
1330
1331 struct KindAndFlags {
1332   KindAndFlags() : kind(kindA), flags(0) { }
1333   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
1334   Kind        kind;
1335   uint32_t    flags;
1336 };
1337
1338 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
1339
1340 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
1341
1342 namespace llvm {
1343 namespace yaml {
1344   template <>
1345   struct ScalarEnumerationTraits<AFlags> {
1346     static void enumeration(IO &io, AFlags &value) {
1347       io.enumCase(value, "a1",  a1);
1348       io.enumCase(value, "a2",  a2);
1349       io.enumCase(value, "a3",  a3);
1350     }
1351   };
1352   template <>
1353   struct ScalarEnumerationTraits<BFlags> {
1354     static void enumeration(IO &io, BFlags &value) {
1355       io.enumCase(value, "b1",  b1);
1356       io.enumCase(value, "b2",  b2);
1357       io.enumCase(value, "b3",  b3);
1358     }
1359   };
1360   template <>
1361   struct ScalarEnumerationTraits<Kind> {
1362     static void enumeration(IO &io, Kind &value) {
1363       io.enumCase(value, "A",  kindA);
1364       io.enumCase(value, "B",  kindB);
1365     }
1366   };
1367   template <>
1368   struct MappingTraits<KindAndFlags> {
1369     static void mapping(IO &io, KindAndFlags& kf) {
1370       io.mapRequired("kind",  kf.kind);
1371       // Type of "flags" field varies depending on "kind" field.
1372       // Use memcpy here to avoid breaking strict aliasing rules.
1373       if (kf.kind == kindA) {
1374         AFlags aflags = static_cast<AFlags>(kf.flags);
1375         io.mapRequired("flags", aflags);
1376         kf.flags = aflags;
1377       } else {
1378         BFlags bflags = static_cast<BFlags>(kf.flags);
1379         io.mapRequired("flags", bflags);
1380         kf.flags = bflags;
1381       }
1382     }
1383   };
1384 }
1385 }
1386
1387
1388 //
1389 // Test the reading of a yaml sequence dynamic types
1390 //
1391 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
1392   KindAndFlagsSequence seq;
1393   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
1394   yin >> seq;
1395
1396   EXPECT_FALSE(yin.error());
1397   EXPECT_EQ(seq.size(), 2UL);
1398   EXPECT_EQ(seq[0].kind,  kindA);
1399   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
1400   EXPECT_EQ(seq[1].kind,  kindB);
1401   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
1402 }
1403
1404 //
1405 // Test writing then reading back dynamic types
1406 //
1407 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
1408   std::string intermediate;
1409   {
1410     KindAndFlagsSequence seq;
1411     seq.push_back(KindAndFlags(kindA,a1));
1412     seq.push_back(KindAndFlags(kindB,b1));
1413     seq.push_back(KindAndFlags(kindA,a2));
1414     seq.push_back(KindAndFlags(kindB,b2));
1415     seq.push_back(KindAndFlags(kindA,a3));
1416
1417     llvm::raw_string_ostream ostr(intermediate);
1418     Output yout(ostr);
1419     yout << seq;
1420   }
1421   {
1422     Input yin(intermediate);
1423     KindAndFlagsSequence seq2;
1424     yin >> seq2;
1425
1426     EXPECT_FALSE(yin.error());
1427     EXPECT_EQ(seq2.size(), 5UL);
1428     EXPECT_EQ(seq2[0].kind,  kindA);
1429     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
1430     EXPECT_EQ(seq2[1].kind,  kindB);
1431     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
1432     EXPECT_EQ(seq2[2].kind,  kindA);
1433     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
1434     EXPECT_EQ(seq2[3].kind,  kindB);
1435     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
1436     EXPECT_EQ(seq2[4].kind,  kindA);
1437     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
1438   }
1439 }
1440
1441
1442 //===----------------------------------------------------------------------===//
1443 //  Test document list
1444 //===----------------------------------------------------------------------===//
1445
1446 struct FooBarMap {
1447   int foo;
1448   int bar;
1449 };
1450 typedef std::vector<FooBarMap> FooBarMapDocumentList;
1451
1452 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
1453
1454
1455 namespace llvm {
1456 namespace yaml {
1457   template <>
1458   struct MappingTraits<FooBarMap> {
1459     static void mapping(IO &io, FooBarMap& fb) {
1460       io.mapRequired("foo",    fb.foo);
1461       io.mapRequired("bar",    fb.bar);
1462     }
1463   };
1464 }
1465 }
1466
1467
1468 //
1469 // Test the reading of a yaml mapping
1470 //
1471 TEST(YAMLIO, TestDocRead) {
1472   FooBarMap doc;
1473   Input yin("---\nfoo:  3\nbar:  5\n...\n");
1474   yin >> doc;
1475
1476   EXPECT_FALSE(yin.error());
1477   EXPECT_EQ(doc.foo, 3);
1478   EXPECT_EQ(doc.bar,5);
1479 }
1480
1481
1482
1483 //
1484 // Test writing then reading back a sequence of mappings
1485 //
1486 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
1487   std::string intermediate;
1488   {
1489     FooBarMap doc1;
1490     doc1.foo = 10;
1491     doc1.bar = -3;
1492     FooBarMap doc2;
1493     doc2.foo = 257;
1494     doc2.bar = 0;
1495     std::vector<FooBarMap> docList;
1496     docList.push_back(doc1);
1497     docList.push_back(doc2);
1498
1499     llvm::raw_string_ostream ostr(intermediate);
1500     Output yout(ostr);
1501     yout << docList;
1502   }
1503
1504
1505   {
1506     Input yin(intermediate);
1507     std::vector<FooBarMap> docList2;
1508     yin >> docList2;
1509
1510     EXPECT_FALSE(yin.error());
1511     EXPECT_EQ(docList2.size(), 2UL);
1512     FooBarMap& map1 = docList2[0];
1513     FooBarMap& map2 = docList2[1];
1514     EXPECT_EQ(map1.foo, 10);
1515     EXPECT_EQ(map1.bar, -3);
1516     EXPECT_EQ(map2.foo, 257);
1517     EXPECT_EQ(map2.bar, 0);
1518   }
1519 }
1520
1521 //===----------------------------------------------------------------------===//
1522 //  Test document tags
1523 //===----------------------------------------------------------------------===//
1524
1525 struct MyDouble {
1526   MyDouble() : value(0.0) { }
1527   MyDouble(double x) : value(x) { }
1528   double value;
1529 };
1530
1531 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
1532
1533
1534 namespace llvm {
1535 namespace yaml {
1536   template <>
1537   struct MappingTraits<MyDouble> {
1538     static void mapping(IO &io, MyDouble &d) {
1539       if (io.mapTag("!decimal", true)) {
1540         mappingDecimal(io, d);
1541       } else if (io.mapTag("!fraction")) {
1542         mappingFraction(io, d);
1543       }
1544     }
1545     static void mappingDecimal(IO &io, MyDouble &d) {
1546       io.mapRequired("value", d.value);
1547     }
1548     static void mappingFraction(IO &io, MyDouble &d) {
1549         double num, denom;
1550         io.mapRequired("numerator",      num);
1551         io.mapRequired("denominator",    denom);
1552         // convert fraction to double
1553         d.value = num/denom;
1554     }
1555   };
1556  }
1557 }
1558
1559
1560 //
1561 // Test the reading of two different tagged yaml documents.
1562 //
1563 TEST(YAMLIO, TestTaggedDocuments) {
1564   std::vector<MyDouble> docList;
1565   Input yin("--- !decimal\nvalue:  3.0\n"
1566             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
1567   yin >> docList;
1568   EXPECT_FALSE(yin.error());
1569   EXPECT_EQ(docList.size(), 2UL);
1570   EXPECT_EQ(docList[0].value, 3.0);
1571   EXPECT_EQ(docList[1].value, 4.5);
1572 }
1573
1574
1575
1576 //
1577 // Test writing then reading back tagged documents
1578 //
1579 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1580   std::string intermediate;
1581   {
1582     MyDouble a(10.25);
1583     MyDouble b(-3.75);
1584     std::vector<MyDouble> docList;
1585     docList.push_back(a);
1586     docList.push_back(b);
1587
1588     llvm::raw_string_ostream ostr(intermediate);
1589     Output yout(ostr);
1590     yout << docList;
1591   }
1592
1593   {
1594     Input yin(intermediate);
1595     std::vector<MyDouble> docList2;
1596     yin >> docList2;
1597
1598     EXPECT_FALSE(yin.error());
1599     EXPECT_EQ(docList2.size(), 2UL);
1600     EXPECT_EQ(docList2[0].value, 10.25);
1601     EXPECT_EQ(docList2[1].value, -3.75);
1602   }
1603 }
1604
1605
1606 //===----------------------------------------------------------------------===//
1607 //  Test mapping validation
1608 //===----------------------------------------------------------------------===//
1609
1610 struct MyValidation {
1611   double value;
1612 };
1613
1614 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
1615
1616 namespace llvm {
1617 namespace yaml {
1618   template <>
1619   struct MappingTraits<MyValidation> {
1620     static void mapping(IO &io, MyValidation &d) {
1621         io.mapRequired("value", d.value);
1622     }
1623     static StringRef validate(IO &io, MyValidation &d) {
1624         if (d.value < 0)
1625           return "negative value";
1626         return StringRef();
1627     }
1628   };
1629  }
1630 }
1631
1632
1633 //
1634 // Test that validate() is called and complains about the negative value.
1635 //
1636 TEST(YAMLIO, TestValidatingInput) {
1637   std::vector<MyValidation> docList;
1638   Input yin("--- \nvalue:  3.0\n"
1639             "--- \nvalue:  -1.0\n...\n",
1640             nullptr, suppressErrorMessages);
1641   yin >> docList;
1642   EXPECT_TRUE(!!yin.error());
1643 }
1644
1645 //===----------------------------------------------------------------------===//
1646 //  Test flow mapping
1647 //===----------------------------------------------------------------------===//
1648
1649 struct FlowFooBar {
1650   int foo;
1651   int bar;
1652
1653   FlowFooBar() : foo(0), bar(0) {}
1654   FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
1655 };
1656
1657 typedef std::vector<FlowFooBar> FlowFooBarSequence;
1658
1659 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
1660
1661 struct FlowFooBarDoc {
1662   FlowFooBar attribute;
1663   FlowFooBarSequence seq;
1664 };
1665
1666 namespace llvm {
1667 namespace yaml {
1668   template <>
1669   struct MappingTraits<FlowFooBar> {
1670     static void mapping(IO &io, FlowFooBar &fb) {
1671       io.mapRequired("foo", fb.foo);
1672       io.mapRequired("bar", fb.bar);
1673     }
1674
1675     static const bool flow = true;
1676   };
1677
1678   template <>
1679   struct MappingTraits<FlowFooBarDoc> {
1680     static void mapping(IO &io, FlowFooBarDoc &fb) {
1681       io.mapRequired("attribute", fb.attribute);
1682       io.mapRequired("seq", fb.seq);
1683     }
1684   };
1685 }
1686 }
1687
1688 //
1689 // Test writing then reading back custom mappings
1690 //
1691 TEST(YAMLIO, TestReadWriteMyFlowMapping) {
1692   std::string intermediate;
1693   {
1694     FlowFooBarDoc doc;
1695     doc.attribute = FlowFooBar(42, 907);
1696     doc.seq.push_back(FlowFooBar(1, 2));
1697     doc.seq.push_back(FlowFooBar(0, 0));
1698     doc.seq.push_back(FlowFooBar(-1, 1024));
1699
1700     llvm::raw_string_ostream ostr(intermediate);
1701     Output yout(ostr);
1702     yout << doc;
1703
1704     // Verify that mappings were written in flow style
1705     ostr.flush();
1706     llvm::StringRef flowOut(intermediate);
1707     EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
1708     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
1709     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
1710     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
1711   }
1712
1713   {
1714     Input yin(intermediate);
1715     FlowFooBarDoc doc2;
1716     yin >> doc2;
1717
1718     EXPECT_FALSE(yin.error());
1719     EXPECT_EQ(doc2.attribute.foo, 42);
1720     EXPECT_EQ(doc2.attribute.bar, 907);
1721     EXPECT_EQ(doc2.seq.size(), 3UL);
1722     EXPECT_EQ(doc2.seq[0].foo, 1);
1723     EXPECT_EQ(doc2.seq[0].bar, 2);
1724     EXPECT_EQ(doc2.seq[1].foo, 0);
1725     EXPECT_EQ(doc2.seq[1].bar, 0);
1726     EXPECT_EQ(doc2.seq[2].foo, -1);
1727     EXPECT_EQ(doc2.seq[2].bar, 1024);
1728   }
1729 }
1730
1731 //===----------------------------------------------------------------------===//
1732 //  Test error handling
1733 //===----------------------------------------------------------------------===//
1734
1735 //
1736 // Test error handling of unknown enumerated scalar
1737 //
1738 TEST(YAMLIO, TestColorsReadError) {
1739   ColorMap map;
1740   Input yin("---\n"
1741             "c1:  blue\n"
1742             "c2:  purple\n"
1743             "c3:  green\n"
1744             "...\n",
1745             /*Ctxt=*/nullptr,
1746             suppressErrorMessages);
1747   yin >> map;
1748   EXPECT_TRUE(!!yin.error());
1749 }
1750
1751
1752 //
1753 // Test error handling of flow sequence with unknown value
1754 //
1755 TEST(YAMLIO, TestFlagsReadError) {
1756   FlagsMap map;
1757   Input yin("---\n"
1758             "f1:  [ big ]\n"
1759             "f2:  [ round, hollow ]\n"
1760             "f3:  []\n"
1761             "...\n",
1762             /*Ctxt=*/nullptr,
1763             suppressErrorMessages);
1764   yin >> map;
1765
1766   EXPECT_TRUE(!!yin.error());
1767 }
1768
1769
1770 //
1771 // Test error handling reading built-in uint8_t type
1772 //
1773 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1774   std::vector<uint8_t> seq;
1775   Input yin("---\n"
1776             "- 255\n"
1777             "- 0\n"
1778             "- 257\n"
1779             "...\n",
1780             /*Ctxt=*/nullptr,
1781             suppressErrorMessages);
1782   yin >> seq;
1783
1784   EXPECT_TRUE(!!yin.error());
1785 }
1786
1787
1788 //
1789 // Test error handling reading built-in uint16_t type
1790 //
1791 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1792   std::vector<uint16_t> seq;
1793   Input yin("---\n"
1794             "- 65535\n"
1795             "- 0\n"
1796             "- 66000\n"
1797             "...\n",
1798             /*Ctxt=*/nullptr,
1799             suppressErrorMessages);
1800   yin >> seq;
1801
1802   EXPECT_TRUE(!!yin.error());
1803 }
1804
1805
1806 //
1807 // Test error handling reading built-in uint32_t type
1808 //
1809 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1810   std::vector<uint32_t> seq;
1811   Input yin("---\n"
1812             "- 4000000000\n"
1813             "- 0\n"
1814             "- 5000000000\n"
1815             "...\n",
1816             /*Ctxt=*/nullptr,
1817             suppressErrorMessages);
1818   yin >> seq;
1819
1820   EXPECT_TRUE(!!yin.error());
1821 }
1822
1823
1824 //
1825 // Test error handling reading built-in uint64_t type
1826 //
1827 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1828   std::vector<uint64_t> seq;
1829   Input yin("---\n"
1830             "- 18446744073709551615\n"
1831             "- 0\n"
1832             "- 19446744073709551615\n"
1833             "...\n",
1834             /*Ctxt=*/nullptr,
1835             suppressErrorMessages);
1836   yin >> seq;
1837
1838   EXPECT_TRUE(!!yin.error());
1839 }
1840
1841
1842 //
1843 // Test error handling reading built-in int8_t type
1844 //
1845 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1846   std::vector<int8_t> seq;
1847   Input yin("---\n"
1848             "- -128\n"
1849             "- 0\n"
1850             "- 127\n"
1851             "- 128\n"
1852            "...\n",
1853             /*Ctxt=*/nullptr,
1854             suppressErrorMessages);
1855   yin >> seq;
1856
1857   EXPECT_TRUE(!!yin.error());
1858 }
1859
1860 //
1861 // Test error handling reading built-in int8_t type
1862 //
1863 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1864   std::vector<int8_t> seq;
1865   Input yin("---\n"
1866             "- -128\n"
1867             "- 0\n"
1868             "- 127\n"
1869             "- -129\n"
1870             "...\n",
1871             /*Ctxt=*/nullptr,
1872             suppressErrorMessages);
1873   yin >> seq;
1874
1875   EXPECT_TRUE(!!yin.error());
1876 }
1877
1878
1879 //
1880 // Test error handling reading built-in int16_t type
1881 //
1882 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1883   std::vector<int16_t> seq;
1884   Input yin("---\n"
1885             "- 32767\n"
1886             "- 0\n"
1887             "- -32768\n"
1888             "- -32769\n"
1889             "...\n",
1890             /*Ctxt=*/nullptr,
1891             suppressErrorMessages);
1892   yin >> seq;
1893
1894   EXPECT_TRUE(!!yin.error());
1895 }
1896
1897
1898 //
1899 // Test error handling reading built-in int16_t type
1900 //
1901 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1902   std::vector<int16_t> seq;
1903   Input yin("---\n"
1904             "- 32767\n"
1905             "- 0\n"
1906             "- -32768\n"
1907             "- 32768\n"
1908             "...\n",
1909             /*Ctxt=*/nullptr,
1910             suppressErrorMessages);
1911   yin >> seq;
1912
1913   EXPECT_TRUE(!!yin.error());
1914 }
1915
1916
1917 //
1918 // Test error handling reading built-in int32_t type
1919 //
1920 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1921   std::vector<int32_t> seq;
1922   Input yin("---\n"
1923             "- 2147483647\n"
1924             "- 0\n"
1925             "- -2147483648\n"
1926             "- -2147483649\n"
1927             "...\n",
1928             /*Ctxt=*/nullptr,
1929             suppressErrorMessages);
1930   yin >> seq;
1931
1932   EXPECT_TRUE(!!yin.error());
1933 }
1934
1935 //
1936 // Test error handling reading built-in int32_t type
1937 //
1938 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1939   std::vector<int32_t> seq;
1940   Input yin("---\n"
1941             "- 2147483647\n"
1942             "- 0\n"
1943             "- -2147483648\n"
1944             "- 2147483649\n"
1945             "...\n",
1946             /*Ctxt=*/nullptr,
1947             suppressErrorMessages);
1948   yin >> seq;
1949
1950   EXPECT_TRUE(!!yin.error());
1951 }
1952
1953
1954 //
1955 // Test error handling reading built-in int64_t type
1956 //
1957 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1958   std::vector<int64_t> seq;
1959   Input yin("---\n"
1960             "- -9223372036854775808\n"
1961             "- 0\n"
1962             "- 9223372036854775807\n"
1963             "- -9223372036854775809\n"
1964             "...\n",
1965             /*Ctxt=*/nullptr,
1966             suppressErrorMessages);
1967   yin >> seq;
1968
1969   EXPECT_TRUE(!!yin.error());
1970 }
1971
1972 //
1973 // Test error handling reading built-in int64_t type
1974 //
1975 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1976   std::vector<int64_t> seq;
1977   Input yin("---\n"
1978             "- -9223372036854775808\n"
1979             "- 0\n"
1980             "- 9223372036854775807\n"
1981             "- 9223372036854775809\n"
1982             "...\n",
1983             /*Ctxt=*/nullptr,
1984             suppressErrorMessages);
1985   yin >> seq;
1986
1987   EXPECT_TRUE(!!yin.error());
1988 }
1989
1990 //
1991 // Test error handling reading built-in float type
1992 //
1993 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1994   std::vector<float> seq;
1995   Input yin("---\n"
1996             "- 0.0\n"
1997             "- 1000.1\n"
1998             "- -123.456\n"
1999             "- 1.2.3\n"
2000             "...\n",
2001             /*Ctxt=*/nullptr,
2002             suppressErrorMessages);
2003   yin >> seq;
2004
2005   EXPECT_TRUE(!!yin.error());
2006 }
2007
2008 //
2009 // Test error handling reading built-in float type
2010 //
2011 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
2012   std::vector<double> seq;
2013   Input yin("---\n"
2014             "- 0.0\n"
2015             "- 1000.1\n"
2016             "- -123.456\n"
2017             "- 1.2.3\n"
2018             "...\n",
2019             /*Ctxt=*/nullptr,
2020             suppressErrorMessages);
2021   yin >> seq;
2022
2023   EXPECT_TRUE(!!yin.error());
2024 }
2025
2026 //
2027 // Test error handling reading built-in Hex8 type
2028 //
2029 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
2030 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
2031   std::vector<Hex8> seq;
2032   Input yin("---\n"
2033             "- 0x12\n"
2034             "- 0xFE\n"
2035             "- 0x123\n"
2036             "...\n",
2037             /*Ctxt=*/nullptr,
2038             suppressErrorMessages);
2039   yin >> seq;
2040
2041   EXPECT_TRUE(!!yin.error());
2042 }
2043
2044
2045 //
2046 // Test error handling reading built-in Hex16 type
2047 //
2048 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
2049 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
2050   std::vector<Hex16> seq;
2051   Input yin("---\n"
2052             "- 0x0012\n"
2053             "- 0xFEFF\n"
2054             "- 0x12345\n"
2055             "...\n",
2056             /*Ctxt=*/nullptr,
2057             suppressErrorMessages);
2058   yin >> seq;
2059
2060   EXPECT_TRUE(!!yin.error());
2061 }
2062
2063 //
2064 // Test error handling reading built-in Hex32 type
2065 //
2066 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
2067 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
2068   std::vector<Hex32> seq;
2069   Input yin("---\n"
2070             "- 0x0012\n"
2071             "- 0xFEFF0000\n"
2072             "- 0x1234556789\n"
2073             "...\n",
2074             /*Ctxt=*/nullptr,
2075             suppressErrorMessages);
2076   yin >> seq;
2077
2078   EXPECT_TRUE(!!yin.error());
2079 }
2080
2081 //
2082 // Test error handling reading built-in Hex64 type
2083 //
2084 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
2085 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
2086   std::vector<Hex64> seq;
2087   Input yin("---\n"
2088             "- 0x0012\n"
2089             "- 0xFFEEDDCCBBAA9988\n"
2090             "- 0x12345567890ABCDEF0\n"
2091             "...\n",
2092             /*Ctxt=*/nullptr,
2093             suppressErrorMessages);
2094   yin >> seq;
2095
2096   EXPECT_TRUE(!!yin.error());
2097 }
2098
2099 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
2100   FooBar doc;
2101   {
2102     // We pass the suppressErrorMessages handler to handle the error
2103     // message generated in the constructor of Input.
2104     Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
2105     yin >> doc;
2106     EXPECT_TRUE(!!yin.error());
2107   }
2108
2109   {
2110     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
2111     yin >> doc;
2112     EXPECT_TRUE(!!yin.error());
2113   }
2114 }
2115
2116 struct OptionalTest {
2117   std::vector<int> Numbers;
2118 };
2119
2120 struct OptionalTestSeq {
2121   std::vector<OptionalTest> Tests;
2122 };
2123
2124 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
2125 namespace llvm {
2126 namespace yaml {
2127   template <>
2128   struct MappingTraits<OptionalTest> {
2129     static void mapping(IO& IO, OptionalTest &OT) {
2130       IO.mapOptional("Numbers", OT.Numbers);
2131     }
2132   };
2133
2134   template <>
2135   struct MappingTraits<OptionalTestSeq> {
2136     static void mapping(IO &IO, OptionalTestSeq &OTS) {
2137       IO.mapOptional("Tests", OTS.Tests);
2138     }
2139   };
2140 }
2141 }
2142
2143 TEST(YAMLIO, SequenceElideTest) {
2144   // Test that writing out a purely optional structure with its fields set to
2145   // default followed by other data is properly read back in.
2146   OptionalTestSeq Seq;
2147   OptionalTest One, Two, Three, Four;
2148   int N[] = {1, 2, 3};
2149   Three.Numbers.assign(N, N + 3);
2150   Seq.Tests.push_back(One);
2151   Seq.Tests.push_back(Two);
2152   Seq.Tests.push_back(Three);
2153   Seq.Tests.push_back(Four);
2154
2155   std::string intermediate;
2156   {
2157     llvm::raw_string_ostream ostr(intermediate);
2158     Output yout(ostr);
2159     yout << Seq;
2160   }
2161
2162   Input yin(intermediate);
2163   OptionalTestSeq Seq2;
2164   yin >> Seq2;
2165
2166   EXPECT_FALSE(yin.error());
2167
2168   EXPECT_EQ(4UL, Seq2.Tests.size());
2169
2170   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
2171   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
2172
2173   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
2174   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
2175   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
2176
2177   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
2178 }
2179
2180 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
2181   FooBar doc;
2182   Input yin("");
2183   yin >> doc;
2184   EXPECT_TRUE(!!yin.error());
2185 }
2186
2187 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
2188   OptionalTest doc;
2189   Input yin("");
2190   yin >> doc;
2191   EXPECT_FALSE(yin.error());
2192 }
2193
2194 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
2195   std::vector<uint8_t> seq;
2196   Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
2197   yin >> seq;
2198
2199   EXPECT_FALSE(yin.error());
2200   EXPECT_TRUE(seq.empty());
2201 }
2202
2203 struct FlowMap {
2204   llvm::StringRef str1, str2, str3;
2205   FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3)
2206     : str1(str1), str2(str2), str3(str3) {}
2207 };
2208
2209 struct FlowSeq {
2210   llvm::StringRef str;
2211   FlowSeq(llvm::StringRef S) : str(S) {}
2212   FlowSeq() = default;
2213 };
2214
2215 namespace llvm {
2216 namespace yaml {
2217   template <>
2218   struct MappingTraits<FlowMap> {
2219     static void mapping(IO &io, FlowMap &fm) {
2220       io.mapRequired("str1", fm.str1);
2221       io.mapRequired("str2", fm.str2);
2222       io.mapRequired("str3", fm.str3);
2223     }
2224
2225     static const bool flow = true;
2226   };
2227
2228 template <>
2229 struct ScalarTraits<FlowSeq> {
2230   static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
2231     out << value.str;
2232   }
2233   static StringRef input(StringRef scalar, void*, FlowSeq &value) {
2234     value.str = scalar;
2235     return "";
2236   }
2237
2238   static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
2239 };
2240 }
2241 }
2242
2243 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
2244
2245 TEST(YAMLIO, TestWrapFlow) {
2246   std::string out;
2247   llvm::raw_string_ostream ostr(out);
2248   FlowMap Map("This is str1", "This is str2", "This is str3");
2249   std::vector<FlowSeq> Seq;
2250   Seq.emplace_back("This is str1");
2251   Seq.emplace_back("This is str2");
2252   Seq.emplace_back("This is str3");
2253
2254   {
2255     // 20 is just bellow the total length of the first mapping field.
2256     // We should wreap at every element.
2257     Output yout(ostr, nullptr, 15);
2258
2259     yout << Map;
2260     ostr.flush();
2261     EXPECT_EQ(out,
2262               "---\n"
2263               "{ str1: This is str1, \n"
2264               "  str2: This is str2, \n"
2265               "  str3: This is str3 }\n"
2266               "...\n");
2267     out.clear();
2268
2269     yout << Seq;
2270     ostr.flush();
2271     EXPECT_EQ(out,
2272               "---\n"
2273               "[ This is str1, \n"
2274               "  This is str2, \n"
2275               "  This is str3 ]\n"
2276               "...\n");
2277     out.clear();
2278   }
2279   {
2280     // 25 will allow the second field to be output on the first line.
2281     Output yout(ostr, nullptr, 25);
2282
2283     yout << Map;
2284     ostr.flush();
2285     EXPECT_EQ(out,
2286               "---\n"
2287               "{ str1: This is str1, str2: This is str2, \n"
2288               "  str3: This is str3 }\n"
2289               "...\n");
2290     out.clear();
2291
2292     yout << Seq;
2293     ostr.flush();
2294     EXPECT_EQ(out,
2295               "---\n"
2296               "[ This is str1, This is str2, \n"
2297               "  This is str3 ]\n"
2298               "...\n");
2299     out.clear();
2300   }
2301   {
2302     // 0 means no wrapping.
2303     Output yout(ostr, nullptr, 0);
2304
2305     yout << Map;
2306     ostr.flush();
2307     EXPECT_EQ(out,
2308               "---\n"
2309               "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n"
2310               "...\n");
2311     out.clear();
2312
2313     yout << Seq;
2314     ostr.flush();
2315     EXPECT_EQ(out,
2316               "---\n"
2317               "[ This is str1, This is str2, This is str3 ]\n"
2318               "...\n");
2319     out.clear();
2320   }
2321 }
2322
2323 struct MappingContext {
2324   int A = 0;
2325 };
2326 struct SimpleMap {
2327   int B = 0;
2328   int C = 0;
2329 };
2330
2331 struct NestedMap {
2332   NestedMap(MappingContext &Context) : Context(Context) {}
2333   SimpleMap Simple;
2334   MappingContext &Context;
2335 };
2336
2337 namespace llvm {
2338 namespace yaml {
2339 template <> struct MappingContextTraits<SimpleMap, MappingContext> {
2340   static void mapping(IO &io, SimpleMap &sm, MappingContext &Context) {
2341     io.mapRequired("B", sm.B);
2342     io.mapRequired("C", sm.C);
2343     ++Context.A;
2344     io.mapRequired("Context", Context.A);
2345   }
2346 };
2347
2348 template <> struct MappingTraits<NestedMap> {
2349   static void mapping(IO &io, NestedMap &nm) {
2350     io.mapRequired("Simple", nm.Simple, nm.Context);
2351   }
2352 };
2353 }
2354 }
2355
2356 TEST(YAMLIO, TestMapWithContext) {
2357   MappingContext Context;
2358   NestedMap Nested(Context);
2359   std::string out;
2360   llvm::raw_string_ostream ostr(out);
2361
2362   Output yout(ostr, nullptr, 15);
2363
2364   yout << Nested;
2365   ostr.flush();
2366   EXPECT_EQ(1, Context.A);
2367   EXPECT_EQ("---\n"
2368             "Simple:          \n"
2369             "  B:               0\n"
2370             "  C:               0\n"
2371             "  Context:         1\n"
2372             "...\n",
2373             out);
2374
2375   out.clear();
2376
2377   Nested.Simple.B = 2;
2378   Nested.Simple.C = 3;
2379   yout << Nested;
2380   ostr.flush();
2381   EXPECT_EQ(2, Context.A);
2382   EXPECT_EQ("---\n"
2383             "Simple:          \n"
2384             "  B:               2\n"
2385             "  C:               3\n"
2386             "  Context:         2\n"
2387             "...\n",
2388             out);
2389   out.clear();
2390 }
2391
2392 LLVM_YAML_IS_STRING_MAP(int)
2393
2394 TEST(YAMLIO, TestCustomMapping) {
2395   std::map<std::string, int> x;
2396   x["foo"] = 1;
2397   x["bar"] = 2;
2398
2399   std::string out;
2400   llvm::raw_string_ostream ostr(out);
2401   Output xout(ostr, nullptr, 0);
2402
2403   xout << x;
2404   ostr.flush();
2405   EXPECT_EQ("---\n"
2406             "bar:             2\n"
2407             "foo:             1\n"
2408             "...\n",
2409             out);
2410
2411   Input yin(out);
2412   std::map<std::string, int> y;
2413   yin >> y;
2414   EXPECT_EQ(2ul, y.size());
2415   EXPECT_EQ(1, y["foo"]);
2416   EXPECT_EQ(2, y["bar"]);
2417 }
2418
2419 LLVM_YAML_IS_STRING_MAP(FooBar)
2420
2421 TEST(YAMLIO, TestCustomMappingStruct) {
2422   std::map<std::string, FooBar> x;
2423   x["foo"].foo = 1;
2424   x["foo"].bar = 2;
2425   x["bar"].foo = 3;
2426   x["bar"].bar = 4;
2427
2428   std::string out;
2429   llvm::raw_string_ostream ostr(out);
2430   Output xout(ostr, nullptr, 0);
2431
2432   xout << x;
2433   ostr.flush();
2434   EXPECT_EQ("---\n"
2435             "bar:             \n"
2436             "  foo:             3\n"
2437             "  bar:             4\n"
2438             "foo:             \n"
2439             "  foo:             1\n"
2440             "  bar:             2\n"
2441             "...\n",
2442             out);
2443
2444   Input yin(out);
2445   std::map<std::string, FooBar> y;
2446   yin >> y;
2447   EXPECT_EQ(2ul, y.size());
2448   EXPECT_EQ(1, y["foo"].foo);
2449   EXPECT_EQ(2, y["foo"].bar);
2450   EXPECT_EQ(3, y["bar"].foo);
2451   EXPECT_EQ(4, y["bar"].bar);
2452 }
2453
2454 static void TestEscaped(llvm::StringRef Input, llvm::StringRef Expected) {
2455   std::string out;
2456   llvm::raw_string_ostream ostr(out);
2457   Output xout(ostr, nullptr, 0);
2458
2459   llvm::yaml::EmptyContext Ctx;
2460   yamlize(xout, Input, true, Ctx);
2461
2462   ostr.flush();
2463   EXPECT_EQ(Expected, out);
2464 }
2465
2466 TEST(YAMLIO, TestEscaped) {
2467   // Single quote
2468   TestEscaped("@abc@", "'@abc@'");
2469   // No quote
2470   TestEscaped("abc/", "abc/");
2471   // Double quote non-printable
2472   TestEscaped("\01@abc@", "\"\\x01@abc@\"");
2473   // Double quote inside single quote
2474   TestEscaped("abc\"fdf", "'abc\"fdf'");
2475   // Double quote inside double quote
2476   TestEscaped("\01bc\"fdf", "\"\\x01bc\\\"fdf\"");
2477   // Single quote inside single quote
2478   TestEscaped("abc'fdf", "'abc''fdf'");
2479   // UTF8
2480   TestEscaped("/*параметр*/", "\"/*параметр*/\"");
2481   // UTF8 with single quote inside double quote
2482   TestEscaped("parameter 'параметр' is unused",
2483               "\"parameter 'параметр' is unused\"");
2484 }