Add a C++11 ThreadPool implementation in LLVM
[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 BlockScalarTraits
784 //===----------------------------------------------------------------------===//
785
786 struct MultilineStringType {
787   std::string str;
788 };
789
790 struct MultilineStringTypeMap {
791   MultilineStringType name;
792   MultilineStringType description;
793   MultilineStringType ingredients;
794   MultilineStringType recipes;
795   MultilineStringType warningLabels;
796   MultilineStringType documentation;
797   int price;
798 };
799
800 namespace llvm {
801 namespace yaml {
802   template <>
803   struct MappingTraits<MultilineStringTypeMap> {
804     static void mapping(IO &io, MultilineStringTypeMap& s) {
805       io.mapRequired("name", s.name);
806       io.mapRequired("description", s.description);
807       io.mapRequired("ingredients", s.ingredients);
808       io.mapRequired("recipes", s.recipes);
809       io.mapRequired("warningLabels", s.warningLabels);
810       io.mapRequired("documentation", s.documentation);
811       io.mapRequired("price", s.price);
812      }
813   };
814
815   // MultilineStringType is formatted as a yaml block literal scalar. A value of
816   // "Hello\nWorld" would be represented in yaml as
817   //  |
818   //    Hello
819   //    World
820   template <>
821   struct BlockScalarTraits<MultilineStringType> {
822     static void output(const MultilineStringType &value, void *ctxt,
823                        llvm::raw_ostream &out) {
824       out << value.str;
825     }
826     static StringRef input(StringRef scalar, void *ctxt,
827                            MultilineStringType &value) {
828       value.str = scalar.str();
829       return StringRef();
830     }
831   };
832 }
833 }
834
835 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
836
837 //
838 // Test writing then reading back custom values
839 //
840 TEST(YAMLIO, TestReadWriteMultilineStringType) {
841   std::string intermediate;
842   {
843     MultilineStringTypeMap map;
844     map.name.str = "An Item";
845     map.description.str = "Hello\nWorld";
846     map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n";
847     map.recipes.str = "\n\nTest 1\n\n\n";
848     map.warningLabels.str = "";
849     map.documentation.str = "\n\n";
850     map.price = 350;
851
852     llvm::raw_string_ostream ostr(intermediate);
853     Output yout(ostr);
854     yout << map;
855   }
856   {
857     Input yin(intermediate);
858     MultilineStringTypeMap map2;
859     yin >> map2;
860
861     EXPECT_FALSE(yin.error());
862     EXPECT_EQ(map2.name.str, "An Item\n");
863     EXPECT_EQ(map2.description.str, "Hello\nWorld\n");
864     EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n");
865     EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n");
866     EXPECT_TRUE(map2.warningLabels.str.empty());
867     EXPECT_TRUE(map2.documentation.str.empty());
868     EXPECT_EQ(map2.price, 350);
869   }
870 }
871
872 //
873 // Test writing then reading back custom values
874 //
875 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
876   std::string intermediate;
877   {
878     std::vector<MultilineStringType> documents;
879     MultilineStringType doc;
880     doc.str = "Hello\nWorld";
881     documents.push_back(doc);
882
883     llvm::raw_string_ostream ostr(intermediate);
884     Output yout(ostr);
885     yout << documents;
886
887     // Verify that the block scalar header was written out on the same line
888     // as the document marker.
889     EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |"));
890   }
891   {
892     Input yin(intermediate);
893     std::vector<MultilineStringType> documents2;
894     yin >> documents2;
895
896     EXPECT_FALSE(yin.error());
897     EXPECT_EQ(documents2.size(), size_t(1));
898     EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
899   }
900 }
901
902 TEST(YAMLIO, TestReadWriteBlockScalarValue) {
903   std::string intermediate;
904   {
905     MultilineStringType doc;
906     doc.str = "Just a block\nscalar doc";
907
908     llvm::raw_string_ostream ostr(intermediate);
909     Output yout(ostr);
910     yout << doc;
911   }
912   {
913     Input yin(intermediate);
914     MultilineStringType doc;
915     yin >> doc;
916
917     EXPECT_FALSE(yin.error());
918     EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
919   }
920 }
921
922 //===----------------------------------------------------------------------===//
923 //  Test flow sequences
924 //===----------------------------------------------------------------------===//
925
926 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
927 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
928 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef)
929
930 namespace llvm {
931 namespace yaml {
932   template<>
933   struct ScalarTraits<MyNumber> {
934     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
935       out << value;
936     }
937
938     static StringRef input(StringRef scalar, void *, MyNumber &value) {
939       long long n;
940       if ( getAsSignedInteger(scalar, 0, n) )
941         return "invalid number";
942       value = n;
943       return StringRef();
944     }
945
946     static bool mustQuote(StringRef) { return false; }
947   };
948 }
949 }
950
951 struct NameAndNumbers {
952   llvm::StringRef               name;
953   std::vector<llvm::StringRef>  strings;
954   std::vector<MyNumber>         single;
955   std::vector<MyNumber>         numbers;
956 };
957
958 namespace llvm {
959 namespace yaml {
960   template <>
961   struct MappingTraits<NameAndNumbers> {
962     static void mapping(IO &io, NameAndNumbers& nn) {
963       io.mapRequired("name",     nn.name);
964       io.mapRequired("strings",  nn.strings);
965       io.mapRequired("single",   nn.single);
966       io.mapRequired("numbers",  nn.numbers);
967     }
968   };
969 }
970 }
971
972 typedef std::vector<MyNumber> MyNumberFlowSequence;
973
974 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
975
976 struct NameAndNumbersFlow {
977   llvm::StringRef                    name;
978   std::vector<MyNumberFlowSequence>  sequenceOfNumbers;
979 };
980
981 namespace llvm {
982 namespace yaml {
983   template <>
984   struct MappingTraits<NameAndNumbersFlow> {
985     static void mapping(IO &io, NameAndNumbersFlow& nn) {
986       io.mapRequired("name",     nn.name);
987       io.mapRequired("sequenceOfNumbers",  nn.sequenceOfNumbers);
988     }
989   };
990 }
991 }
992
993 //
994 // Test writing then reading back custom values
995 //
996 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
997   std::string intermediate;
998   {
999     NameAndNumbers map;
1000     map.name  = "hello";
1001     map.strings.push_back(llvm::StringRef("one"));
1002     map.strings.push_back(llvm::StringRef("two"));
1003     map.single.push_back(1);
1004     map.numbers.push_back(10);
1005     map.numbers.push_back(-30);
1006     map.numbers.push_back(1024);
1007
1008     llvm::raw_string_ostream ostr(intermediate);
1009     Output yout(ostr);
1010     yout << map;
1011
1012     // Verify sequences were written in flow style
1013     ostr.flush();
1014     llvm::StringRef flowOut(intermediate);
1015     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
1016     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
1017   }
1018
1019   {
1020     Input yin(intermediate);
1021     NameAndNumbers map2;
1022     yin >> map2;
1023
1024     EXPECT_FALSE(yin.error());
1025     EXPECT_TRUE(map2.name.equals("hello"));
1026     EXPECT_EQ(map2.strings.size(), 2UL);
1027     EXPECT_TRUE(map2.strings[0].equals("one"));
1028     EXPECT_TRUE(map2.strings[1].equals("two"));
1029     EXPECT_EQ(map2.single.size(), 1UL);
1030     EXPECT_EQ(1,       map2.single[0]);
1031     EXPECT_EQ(map2.numbers.size(), 3UL);
1032     EXPECT_EQ(10,      map2.numbers[0]);
1033     EXPECT_EQ(-30,     map2.numbers[1]);
1034     EXPECT_EQ(1024,    map2.numbers[2]);
1035   }
1036 }
1037
1038
1039 //
1040 // Test writing then reading back a sequence of flow sequences.
1041 //
1042 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
1043   std::string intermediate;
1044   {
1045     NameAndNumbersFlow map;
1046     map.name  = "hello";
1047     MyNumberFlowSequence single = { 0 };
1048     MyNumberFlowSequence numbers = { 12, 1, -512 };
1049     map.sequenceOfNumbers.push_back(single);
1050     map.sequenceOfNumbers.push_back(numbers);
1051     map.sequenceOfNumbers.push_back(MyNumberFlowSequence());
1052
1053     llvm::raw_string_ostream ostr(intermediate);
1054     Output yout(ostr);
1055     yout << map;
1056
1057     // Verify sequences were written in flow style
1058     // and that the parent sequence used '-'.
1059     ostr.flush();
1060     llvm::StringRef flowOut(intermediate);
1061     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]"));
1062     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]"));
1063     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [  ]"));
1064   }
1065
1066   {
1067     Input yin(intermediate);
1068     NameAndNumbersFlow map2;
1069     yin >> map2;
1070
1071     EXPECT_FALSE(yin.error());
1072     EXPECT_TRUE(map2.name.equals("hello"));
1073     EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL);
1074     EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL);
1075     EXPECT_EQ(0,    map2.sequenceOfNumbers[0][0]);
1076     EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL);
1077     EXPECT_EQ(12,   map2.sequenceOfNumbers[1][0]);
1078     EXPECT_EQ(1,    map2.sequenceOfNumbers[1][1]);
1079     EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]);
1080     EXPECT_TRUE(map2.sequenceOfNumbers[2].empty());
1081   }
1082 }
1083
1084 //===----------------------------------------------------------------------===//
1085 //  Test normalizing/denormalizing
1086 //===----------------------------------------------------------------------===//
1087
1088 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
1089
1090 typedef std::vector<TotalSeconds> SecondsSequence;
1091
1092 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
1093
1094
1095 namespace llvm {
1096 namespace yaml {
1097   template <>
1098   struct MappingTraits<TotalSeconds> {
1099
1100     class NormalizedSeconds {
1101     public:
1102       NormalizedSeconds(IO &io)
1103         : hours(0), minutes(0), seconds(0) {
1104       }
1105       NormalizedSeconds(IO &, TotalSeconds &secs)
1106         : hours(secs/3600),
1107           minutes((secs - (hours*3600))/60),
1108           seconds(secs % 60) {
1109       }
1110       TotalSeconds denormalize(IO &) {
1111         return TotalSeconds(hours*3600 + minutes*60 + seconds);
1112       }
1113
1114       uint32_t     hours;
1115       uint8_t      minutes;
1116       uint8_t      seconds;
1117     };
1118
1119     static void mapping(IO &io, TotalSeconds &secs) {
1120       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
1121
1122       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
1123       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
1124       io.mapRequired("seconds",  keys->seconds);
1125     }
1126   };
1127 }
1128 }
1129
1130
1131 //
1132 // Test the reading of a yaml sequence of mappings
1133 //
1134 TEST(YAMLIO, TestReadMySecondsSequence) {
1135   SecondsSequence seq;
1136   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
1137   yin >> seq;
1138
1139   EXPECT_FALSE(yin.error());
1140   EXPECT_EQ(seq.size(), 2UL);
1141   EXPECT_EQ(seq[0], 3605U);
1142   EXPECT_EQ(seq[1], 59U);
1143 }
1144
1145
1146 //
1147 // Test writing then reading back custom values
1148 //
1149 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
1150   std::string intermediate;
1151   {
1152     SecondsSequence seq;
1153     seq.push_back(4000);
1154     seq.push_back(500);
1155     seq.push_back(59);
1156
1157     llvm::raw_string_ostream ostr(intermediate);
1158     Output yout(ostr);
1159     yout << seq;
1160   }
1161   {
1162     Input yin(intermediate);
1163     SecondsSequence seq2;
1164     yin >> seq2;
1165
1166     EXPECT_FALSE(yin.error());
1167     EXPECT_EQ(seq2.size(), 3UL);
1168     EXPECT_EQ(seq2[0], 4000U);
1169     EXPECT_EQ(seq2[1], 500U);
1170     EXPECT_EQ(seq2[2], 59U);
1171   }
1172 }
1173
1174
1175 //===----------------------------------------------------------------------===//
1176 //  Test dynamic typing
1177 //===----------------------------------------------------------------------===//
1178
1179 enum AFlags {
1180     a1,
1181     a2,
1182     a3
1183 };
1184
1185 enum BFlags {
1186     b1,
1187     b2,
1188     b3
1189 };
1190
1191 enum Kind {
1192     kindA,
1193     kindB
1194 };
1195
1196 struct KindAndFlags {
1197   KindAndFlags() : kind(kindA), flags(0) { }
1198   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
1199   Kind        kind;
1200   uint32_t    flags;
1201 };
1202
1203 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
1204
1205 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
1206
1207 namespace llvm {
1208 namespace yaml {
1209   template <>
1210   struct ScalarEnumerationTraits<AFlags> {
1211     static void enumeration(IO &io, AFlags &value) {
1212       io.enumCase(value, "a1",  a1);
1213       io.enumCase(value, "a2",  a2);
1214       io.enumCase(value, "a3",  a3);
1215     }
1216   };
1217   template <>
1218   struct ScalarEnumerationTraits<BFlags> {
1219     static void enumeration(IO &io, BFlags &value) {
1220       io.enumCase(value, "b1",  b1);
1221       io.enumCase(value, "b2",  b2);
1222       io.enumCase(value, "b3",  b3);
1223     }
1224   };
1225   template <>
1226   struct ScalarEnumerationTraits<Kind> {
1227     static void enumeration(IO &io, Kind &value) {
1228       io.enumCase(value, "A",  kindA);
1229       io.enumCase(value, "B",  kindB);
1230     }
1231   };
1232   template <>
1233   struct MappingTraits<KindAndFlags> {
1234     static void mapping(IO &io, KindAndFlags& kf) {
1235       io.mapRequired("kind",  kf.kind);
1236       // Type of "flags" field varies depending on "kind" field.
1237       // Use memcpy here to avoid breaking strict aliasing rules.
1238       if (kf.kind == kindA) {
1239         AFlags aflags = static_cast<AFlags>(kf.flags);
1240         io.mapRequired("flags", aflags);
1241         kf.flags = aflags;
1242       } else {
1243         BFlags bflags = static_cast<BFlags>(kf.flags);
1244         io.mapRequired("flags", bflags);
1245         kf.flags = bflags;
1246       }
1247     }
1248   };
1249 }
1250 }
1251
1252
1253 //
1254 // Test the reading of a yaml sequence dynamic types
1255 //
1256 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
1257   KindAndFlagsSequence seq;
1258   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
1259   yin >> seq;
1260
1261   EXPECT_FALSE(yin.error());
1262   EXPECT_EQ(seq.size(), 2UL);
1263   EXPECT_EQ(seq[0].kind,  kindA);
1264   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
1265   EXPECT_EQ(seq[1].kind,  kindB);
1266   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
1267 }
1268
1269 //
1270 // Test writing then reading back dynamic types
1271 //
1272 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
1273   std::string intermediate;
1274   {
1275     KindAndFlagsSequence seq;
1276     seq.push_back(KindAndFlags(kindA,a1));
1277     seq.push_back(KindAndFlags(kindB,b1));
1278     seq.push_back(KindAndFlags(kindA,a2));
1279     seq.push_back(KindAndFlags(kindB,b2));
1280     seq.push_back(KindAndFlags(kindA,a3));
1281
1282     llvm::raw_string_ostream ostr(intermediate);
1283     Output yout(ostr);
1284     yout << seq;
1285   }
1286   {
1287     Input yin(intermediate);
1288     KindAndFlagsSequence seq2;
1289     yin >> seq2;
1290
1291     EXPECT_FALSE(yin.error());
1292     EXPECT_EQ(seq2.size(), 5UL);
1293     EXPECT_EQ(seq2[0].kind,  kindA);
1294     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
1295     EXPECT_EQ(seq2[1].kind,  kindB);
1296     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
1297     EXPECT_EQ(seq2[2].kind,  kindA);
1298     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
1299     EXPECT_EQ(seq2[3].kind,  kindB);
1300     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
1301     EXPECT_EQ(seq2[4].kind,  kindA);
1302     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
1303   }
1304 }
1305
1306
1307 //===----------------------------------------------------------------------===//
1308 //  Test document list
1309 //===----------------------------------------------------------------------===//
1310
1311 struct FooBarMap {
1312   int foo;
1313   int bar;
1314 };
1315 typedef std::vector<FooBarMap> FooBarMapDocumentList;
1316
1317 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
1318
1319
1320 namespace llvm {
1321 namespace yaml {
1322   template <>
1323   struct MappingTraits<FooBarMap> {
1324     static void mapping(IO &io, FooBarMap& fb) {
1325       io.mapRequired("foo",    fb.foo);
1326       io.mapRequired("bar",    fb.bar);
1327     }
1328   };
1329 }
1330 }
1331
1332
1333 //
1334 // Test the reading of a yaml mapping
1335 //
1336 TEST(YAMLIO, TestDocRead) {
1337   FooBarMap doc;
1338   Input yin("---\nfoo:  3\nbar:  5\n...\n");
1339   yin >> doc;
1340
1341   EXPECT_FALSE(yin.error());
1342   EXPECT_EQ(doc.foo, 3);
1343   EXPECT_EQ(doc.bar,5);
1344 }
1345
1346
1347
1348 //
1349 // Test writing then reading back a sequence of mappings
1350 //
1351 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
1352   std::string intermediate;
1353   {
1354     FooBarMap doc1;
1355     doc1.foo = 10;
1356     doc1.bar = -3;
1357     FooBarMap doc2;
1358     doc2.foo = 257;
1359     doc2.bar = 0;
1360     std::vector<FooBarMap> docList;
1361     docList.push_back(doc1);
1362     docList.push_back(doc2);
1363
1364     llvm::raw_string_ostream ostr(intermediate);
1365     Output yout(ostr);
1366     yout << docList;
1367   }
1368
1369
1370   {
1371     Input yin(intermediate);
1372     std::vector<FooBarMap> docList2;
1373     yin >> docList2;
1374
1375     EXPECT_FALSE(yin.error());
1376     EXPECT_EQ(docList2.size(), 2UL);
1377     FooBarMap& map1 = docList2[0];
1378     FooBarMap& map2 = docList2[1];
1379     EXPECT_EQ(map1.foo, 10);
1380     EXPECT_EQ(map1.bar, -3);
1381     EXPECT_EQ(map2.foo, 257);
1382     EXPECT_EQ(map2.bar, 0);
1383   }
1384 }
1385
1386 //===----------------------------------------------------------------------===//
1387 //  Test document tags
1388 //===----------------------------------------------------------------------===//
1389
1390 struct MyDouble {
1391   MyDouble() : value(0.0) { }
1392   MyDouble(double x) : value(x) { }
1393   double value;
1394 };
1395
1396 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
1397
1398
1399 namespace llvm {
1400 namespace yaml {
1401   template <>
1402   struct MappingTraits<MyDouble> {
1403     static void mapping(IO &io, MyDouble &d) {
1404       if (io.mapTag("!decimal", true)) {
1405         mappingDecimal(io, d);
1406       } else if (io.mapTag("!fraction")) {
1407         mappingFraction(io, d);
1408       }
1409     }
1410     static void mappingDecimal(IO &io, MyDouble &d) {
1411       io.mapRequired("value", d.value);
1412     }
1413     static void mappingFraction(IO &io, MyDouble &d) {
1414         double num, denom;
1415         io.mapRequired("numerator",      num);
1416         io.mapRequired("denominator",    denom);
1417         // convert fraction to double
1418         d.value = num/denom;
1419     }
1420   };
1421  }
1422 }
1423
1424
1425 //
1426 // Test the reading of two different tagged yaml documents.
1427 //
1428 TEST(YAMLIO, TestTaggedDocuments) {
1429   std::vector<MyDouble> docList;
1430   Input yin("--- !decimal\nvalue:  3.0\n"
1431             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
1432   yin >> docList;
1433   EXPECT_FALSE(yin.error());
1434   EXPECT_EQ(docList.size(), 2UL);
1435   EXPECT_EQ(docList[0].value, 3.0);
1436   EXPECT_EQ(docList[1].value, 4.5);
1437 }
1438
1439
1440
1441 //
1442 // Test writing then reading back tagged documents
1443 //
1444 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1445   std::string intermediate;
1446   {
1447     MyDouble a(10.25);
1448     MyDouble b(-3.75);
1449     std::vector<MyDouble> docList;
1450     docList.push_back(a);
1451     docList.push_back(b);
1452
1453     llvm::raw_string_ostream ostr(intermediate);
1454     Output yout(ostr);
1455     yout << docList;
1456   }
1457
1458   {
1459     Input yin(intermediate);
1460     std::vector<MyDouble> docList2;
1461     yin >> docList2;
1462
1463     EXPECT_FALSE(yin.error());
1464     EXPECT_EQ(docList2.size(), 2UL);
1465     EXPECT_EQ(docList2[0].value, 10.25);
1466     EXPECT_EQ(docList2[1].value, -3.75);
1467   }
1468 }
1469
1470
1471 //===----------------------------------------------------------------------===//
1472 //  Test mapping validation
1473 //===----------------------------------------------------------------------===//
1474
1475 struct MyValidation {
1476   double value;
1477 };
1478
1479 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
1480
1481 namespace llvm {
1482 namespace yaml {
1483   template <>
1484   struct MappingTraits<MyValidation> {
1485     static void mapping(IO &io, MyValidation &d) {
1486         io.mapRequired("value", d.value);
1487     }
1488     static StringRef validate(IO &io, MyValidation &d) {
1489         if (d.value < 0)
1490           return "negative value";
1491         return StringRef();
1492     }
1493   };
1494  }
1495 }
1496
1497
1498 //
1499 // Test that validate() is called and complains about the negative value.
1500 //
1501 TEST(YAMLIO, TestValidatingInput) {
1502   std::vector<MyValidation> docList;
1503   Input yin("--- \nvalue:  3.0\n"
1504             "--- \nvalue:  -1.0\n...\n",
1505             nullptr, suppressErrorMessages);
1506   yin >> docList;
1507   EXPECT_TRUE(!!yin.error());
1508 }
1509
1510 //===----------------------------------------------------------------------===//
1511 //  Test flow mapping
1512 //===----------------------------------------------------------------------===//
1513
1514 struct FlowFooBar {
1515   int foo;
1516   int bar;
1517
1518   FlowFooBar() : foo(0), bar(0) {}
1519   FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
1520 };
1521
1522 typedef std::vector<FlowFooBar> FlowFooBarSequence;
1523
1524 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
1525
1526 struct FlowFooBarDoc {
1527   FlowFooBar attribute;
1528   FlowFooBarSequence seq;
1529 };
1530
1531 namespace llvm {
1532 namespace yaml {
1533   template <>
1534   struct MappingTraits<FlowFooBar> {
1535     static void mapping(IO &io, FlowFooBar &fb) {
1536       io.mapRequired("foo", fb.foo);
1537       io.mapRequired("bar", fb.bar);
1538     }
1539
1540     static const bool flow = true;
1541   };
1542
1543   template <>
1544   struct MappingTraits<FlowFooBarDoc> {
1545     static void mapping(IO &io, FlowFooBarDoc &fb) {
1546       io.mapRequired("attribute", fb.attribute);
1547       io.mapRequired("seq", fb.seq);
1548     }
1549   };
1550 }
1551 }
1552
1553 //
1554 // Test writing then reading back custom mappings
1555 //
1556 TEST(YAMLIO, TestReadWriteMyFlowMapping) {
1557   std::string intermediate;
1558   {
1559     FlowFooBarDoc doc;
1560     doc.attribute = FlowFooBar(42, 907);
1561     doc.seq.push_back(FlowFooBar(1, 2));
1562     doc.seq.push_back(FlowFooBar(0, 0));
1563     doc.seq.push_back(FlowFooBar(-1, 1024));
1564
1565     llvm::raw_string_ostream ostr(intermediate);
1566     Output yout(ostr);
1567     yout << doc;
1568
1569     // Verify that mappings were written in flow style
1570     ostr.flush();
1571     llvm::StringRef flowOut(intermediate);
1572     EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
1573     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
1574     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
1575     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
1576   }
1577
1578   {
1579     Input yin(intermediate);
1580     FlowFooBarDoc doc2;
1581     yin >> doc2;
1582
1583     EXPECT_FALSE(yin.error());
1584     EXPECT_EQ(doc2.attribute.foo, 42);
1585     EXPECT_EQ(doc2.attribute.bar, 907);
1586     EXPECT_EQ(doc2.seq.size(), 3UL);
1587     EXPECT_EQ(doc2.seq[0].foo, 1);
1588     EXPECT_EQ(doc2.seq[0].bar, 2);
1589     EXPECT_EQ(doc2.seq[1].foo, 0);
1590     EXPECT_EQ(doc2.seq[1].bar, 0);
1591     EXPECT_EQ(doc2.seq[2].foo, -1);
1592     EXPECT_EQ(doc2.seq[2].bar, 1024);
1593   }
1594 }
1595
1596 //===----------------------------------------------------------------------===//
1597 //  Test error handling
1598 //===----------------------------------------------------------------------===//
1599
1600 //
1601 // Test error handling of unknown enumerated scalar
1602 //
1603 TEST(YAMLIO, TestColorsReadError) {
1604   ColorMap map;
1605   Input yin("---\n"
1606             "c1:  blue\n"
1607             "c2:  purple\n"
1608             "c3:  green\n"
1609             "...\n",
1610             /*Ctxt=*/nullptr,
1611             suppressErrorMessages);
1612   yin >> map;
1613   EXPECT_TRUE(!!yin.error());
1614 }
1615
1616
1617 //
1618 // Test error handling of flow sequence with unknown value
1619 //
1620 TEST(YAMLIO, TestFlagsReadError) {
1621   FlagsMap map;
1622   Input yin("---\n"
1623             "f1:  [ big ]\n"
1624             "f2:  [ round, hollow ]\n"
1625             "f3:  []\n"
1626             "...\n",
1627             /*Ctxt=*/nullptr,
1628             suppressErrorMessages);
1629   yin >> map;
1630
1631   EXPECT_TRUE(!!yin.error());
1632 }
1633
1634
1635 //
1636 // Test error handling reading built-in uint8_t type
1637 //
1638 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
1639 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1640   std::vector<uint8_t> seq;
1641   Input yin("---\n"
1642             "- 255\n"
1643             "- 0\n"
1644             "- 257\n"
1645             "...\n",
1646             /*Ctxt=*/nullptr,
1647             suppressErrorMessages);
1648   yin >> seq;
1649
1650   EXPECT_TRUE(!!yin.error());
1651 }
1652
1653
1654 //
1655 // Test error handling reading built-in uint16_t type
1656 //
1657 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
1658 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1659   std::vector<uint16_t> seq;
1660   Input yin("---\n"
1661             "- 65535\n"
1662             "- 0\n"
1663             "- 66000\n"
1664             "...\n",
1665             /*Ctxt=*/nullptr,
1666             suppressErrorMessages);
1667   yin >> seq;
1668
1669   EXPECT_TRUE(!!yin.error());
1670 }
1671
1672
1673 //
1674 // Test error handling reading built-in uint32_t type
1675 //
1676 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
1677 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1678   std::vector<uint32_t> seq;
1679   Input yin("---\n"
1680             "- 4000000000\n"
1681             "- 0\n"
1682             "- 5000000000\n"
1683             "...\n",
1684             /*Ctxt=*/nullptr,
1685             suppressErrorMessages);
1686   yin >> seq;
1687
1688   EXPECT_TRUE(!!yin.error());
1689 }
1690
1691
1692 //
1693 // Test error handling reading built-in uint64_t type
1694 //
1695 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
1696 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1697   std::vector<uint64_t> seq;
1698   Input yin("---\n"
1699             "- 18446744073709551615\n"
1700             "- 0\n"
1701             "- 19446744073709551615\n"
1702             "...\n",
1703             /*Ctxt=*/nullptr,
1704             suppressErrorMessages);
1705   yin >> seq;
1706
1707   EXPECT_TRUE(!!yin.error());
1708 }
1709
1710
1711 //
1712 // Test error handling reading built-in int8_t type
1713 //
1714 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
1715 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1716   std::vector<int8_t> seq;
1717   Input yin("---\n"
1718             "- -128\n"
1719             "- 0\n"
1720             "- 127\n"
1721             "- 128\n"
1722            "...\n",
1723             /*Ctxt=*/nullptr,
1724             suppressErrorMessages);
1725   yin >> seq;
1726
1727   EXPECT_TRUE(!!yin.error());
1728 }
1729
1730 //
1731 // Test error handling reading built-in int8_t type
1732 //
1733 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1734   std::vector<int8_t> seq;
1735   Input yin("---\n"
1736             "- -128\n"
1737             "- 0\n"
1738             "- 127\n"
1739             "- -129\n"
1740             "...\n",
1741             /*Ctxt=*/nullptr,
1742             suppressErrorMessages);
1743   yin >> seq;
1744
1745   EXPECT_TRUE(!!yin.error());
1746 }
1747
1748
1749 //
1750 // Test error handling reading built-in int16_t type
1751 //
1752 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
1753 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1754   std::vector<int16_t> seq;
1755   Input yin("---\n"
1756             "- 32767\n"
1757             "- 0\n"
1758             "- -32768\n"
1759             "- -32769\n"
1760             "...\n",
1761             /*Ctxt=*/nullptr,
1762             suppressErrorMessages);
1763   yin >> seq;
1764
1765   EXPECT_TRUE(!!yin.error());
1766 }
1767
1768
1769 //
1770 // Test error handling reading built-in int16_t type
1771 //
1772 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1773   std::vector<int16_t> seq;
1774   Input yin("---\n"
1775             "- 32767\n"
1776             "- 0\n"
1777             "- -32768\n"
1778             "- 32768\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 int32_t type
1790 //
1791 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
1792 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1793   std::vector<int32_t> seq;
1794   Input yin("---\n"
1795             "- 2147483647\n"
1796             "- 0\n"
1797             "- -2147483648\n"
1798             "- -2147483649\n"
1799             "...\n",
1800             /*Ctxt=*/nullptr,
1801             suppressErrorMessages);
1802   yin >> seq;
1803
1804   EXPECT_TRUE(!!yin.error());
1805 }
1806
1807 //
1808 // Test error handling reading built-in int32_t type
1809 //
1810 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1811   std::vector<int32_t> seq;
1812   Input yin("---\n"
1813             "- 2147483647\n"
1814             "- 0\n"
1815             "- -2147483648\n"
1816             "- 2147483649\n"
1817             "...\n",
1818             /*Ctxt=*/nullptr,
1819             suppressErrorMessages);
1820   yin >> seq;
1821
1822   EXPECT_TRUE(!!yin.error());
1823 }
1824
1825
1826 //
1827 // Test error handling reading built-in int64_t type
1828 //
1829 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
1830 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1831   std::vector<int64_t> seq;
1832   Input yin("---\n"
1833             "- -9223372036854775808\n"
1834             "- 0\n"
1835             "- 9223372036854775807\n"
1836             "- -9223372036854775809\n"
1837             "...\n",
1838             /*Ctxt=*/nullptr,
1839             suppressErrorMessages);
1840   yin >> seq;
1841
1842   EXPECT_TRUE(!!yin.error());
1843 }
1844
1845 //
1846 // Test error handling reading built-in int64_t type
1847 //
1848 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1849   std::vector<int64_t> seq;
1850   Input yin("---\n"
1851             "- -9223372036854775808\n"
1852             "- 0\n"
1853             "- 9223372036854775807\n"
1854             "- 9223372036854775809\n"
1855             "...\n",
1856             /*Ctxt=*/nullptr,
1857             suppressErrorMessages);
1858   yin >> seq;
1859
1860   EXPECT_TRUE(!!yin.error());
1861 }
1862
1863 //
1864 // Test error handling reading built-in float type
1865 //
1866 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
1867 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1868   std::vector<float> seq;
1869   Input yin("---\n"
1870             "- 0.0\n"
1871             "- 1000.1\n"
1872             "- -123.456\n"
1873             "- 1.2.3\n"
1874             "...\n",
1875             /*Ctxt=*/nullptr,
1876             suppressErrorMessages);
1877   yin >> seq;
1878
1879   EXPECT_TRUE(!!yin.error());
1880 }
1881
1882 //
1883 // Test error handling reading built-in float type
1884 //
1885 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
1886 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1887   std::vector<double> seq;
1888   Input yin("---\n"
1889             "- 0.0\n"
1890             "- 1000.1\n"
1891             "- -123.456\n"
1892             "- 1.2.3\n"
1893             "...\n",
1894             /*Ctxt=*/nullptr,
1895             suppressErrorMessages);
1896   yin >> seq;
1897
1898   EXPECT_TRUE(!!yin.error());
1899 }
1900
1901 //
1902 // Test error handling reading built-in Hex8 type
1903 //
1904 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
1905 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
1906   std::vector<Hex8> seq;
1907   Input yin("---\n"
1908             "- 0x12\n"
1909             "- 0xFE\n"
1910             "- 0x123\n"
1911             "...\n",
1912             /*Ctxt=*/nullptr,
1913             suppressErrorMessages);
1914   yin >> seq;
1915
1916   EXPECT_TRUE(!!yin.error());
1917 }
1918
1919
1920 //
1921 // Test error handling reading built-in Hex16 type
1922 //
1923 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
1924 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
1925   std::vector<Hex16> seq;
1926   Input yin("---\n"
1927             "- 0x0012\n"
1928             "- 0xFEFF\n"
1929             "- 0x12345\n"
1930             "...\n",
1931             /*Ctxt=*/nullptr,
1932             suppressErrorMessages);
1933   yin >> seq;
1934
1935   EXPECT_TRUE(!!yin.error());
1936 }
1937
1938 //
1939 // Test error handling reading built-in Hex32 type
1940 //
1941 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
1942 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
1943   std::vector<Hex32> seq;
1944   Input yin("---\n"
1945             "- 0x0012\n"
1946             "- 0xFEFF0000\n"
1947             "- 0x1234556789\n"
1948             "...\n",
1949             /*Ctxt=*/nullptr,
1950             suppressErrorMessages);
1951   yin >> seq;
1952
1953   EXPECT_TRUE(!!yin.error());
1954 }
1955
1956 //
1957 // Test error handling reading built-in Hex64 type
1958 //
1959 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
1960 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
1961   std::vector<Hex64> seq;
1962   Input yin("---\n"
1963             "- 0x0012\n"
1964             "- 0xFFEEDDCCBBAA9988\n"
1965             "- 0x12345567890ABCDEF0\n"
1966             "...\n",
1967             /*Ctxt=*/nullptr,
1968             suppressErrorMessages);
1969   yin >> seq;
1970
1971   EXPECT_TRUE(!!yin.error());
1972 }
1973
1974 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
1975   FooBar doc;
1976   {
1977     // We pass the suppressErrorMessages handler to handle the error
1978     // message generated in the constructor of Input.
1979     Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
1980     yin >> doc;
1981     EXPECT_TRUE(!!yin.error());
1982   }
1983
1984   {
1985     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
1986     yin >> doc;
1987     EXPECT_TRUE(!!yin.error());
1988   }
1989 }
1990
1991 struct OptionalTest {
1992   std::vector<int> Numbers;
1993 };
1994
1995 struct OptionalTestSeq {
1996   std::vector<OptionalTest> Tests;
1997 };
1998
1999 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
2000 namespace llvm {
2001 namespace yaml {
2002   template <>
2003   struct MappingTraits<OptionalTest> {
2004     static void mapping(IO& IO, OptionalTest &OT) {
2005       IO.mapOptional("Numbers", OT.Numbers);
2006     }
2007   };
2008
2009   template <>
2010   struct MappingTraits<OptionalTestSeq> {
2011     static void mapping(IO &IO, OptionalTestSeq &OTS) {
2012       IO.mapOptional("Tests", OTS.Tests);
2013     }
2014   };
2015 }
2016 }
2017
2018 TEST(YAMLIO, SequenceElideTest) {
2019   // Test that writing out a purely optional structure with its fields set to
2020   // default followed by other data is properly read back in.
2021   OptionalTestSeq Seq;
2022   OptionalTest One, Two, Three, Four;
2023   int N[] = {1, 2, 3};
2024   Three.Numbers.assign(N, N + 3);
2025   Seq.Tests.push_back(One);
2026   Seq.Tests.push_back(Two);
2027   Seq.Tests.push_back(Three);
2028   Seq.Tests.push_back(Four);
2029
2030   std::string intermediate;
2031   {
2032     llvm::raw_string_ostream ostr(intermediate);
2033     Output yout(ostr);
2034     yout << Seq;
2035   }
2036
2037   Input yin(intermediate);
2038   OptionalTestSeq Seq2;
2039   yin >> Seq2;
2040
2041   EXPECT_FALSE(yin.error());
2042
2043   EXPECT_EQ(4UL, Seq2.Tests.size());
2044
2045   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
2046   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
2047
2048   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
2049   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
2050   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
2051
2052   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
2053 }
2054
2055 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
2056   FooBar doc;
2057   Input yin("");
2058   yin >> doc;
2059   EXPECT_TRUE(!!yin.error());
2060 }
2061
2062 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
2063   OptionalTest doc;
2064   Input yin("");
2065   yin >> doc;
2066   EXPECT_FALSE(yin.error());
2067 }
2068
2069 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
2070   std::vector<uint8_t> seq;
2071   Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
2072   yin >> seq;
2073
2074   EXPECT_FALSE(yin.error());
2075   EXPECT_TRUE(seq.empty());
2076 }
2077
2078 struct FlowMap {
2079   llvm::StringRef str1, str2, str3;
2080   FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3)
2081     : str1(str1), str2(str2), str3(str3) {}
2082 };
2083
2084 struct FlowSeq {
2085   llvm::StringRef str;
2086   FlowSeq(llvm::StringRef S) : str(S) {}
2087   FlowSeq() = default;
2088 };
2089
2090 namespace llvm {
2091 namespace yaml {
2092   template <>
2093   struct MappingTraits<FlowMap> {
2094     static void mapping(IO &io, FlowMap &fm) {
2095       io.mapRequired("str1", fm.str1);
2096       io.mapRequired("str2", fm.str2);
2097       io.mapRequired("str3", fm.str3);
2098     }
2099
2100     static const bool flow = true;
2101   };
2102
2103 template <>
2104 struct ScalarTraits<FlowSeq> {
2105   static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
2106     out << value.str;
2107   }
2108   static StringRef input(StringRef scalar, void*, FlowSeq &value) {
2109     value.str = scalar;
2110     return "";
2111   }
2112
2113   static bool mustQuote(StringRef S) { return false; }
2114 };
2115 }
2116 }
2117
2118 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
2119
2120 TEST(YAMLIO, TestWrapFlow) {
2121   std::string out;
2122   llvm::raw_string_ostream ostr(out);
2123   FlowMap Map("This is str1", "This is str2", "This is str3");
2124   std::vector<FlowSeq> Seq;
2125   Seq.emplace_back("This is str1");
2126   Seq.emplace_back("This is str2");
2127   Seq.emplace_back("This is str3");
2128
2129   {
2130     // 20 is just bellow the total length of the first mapping field.
2131     // We should wreap at every element.
2132     Output yout(ostr, nullptr, 15);
2133
2134     yout << Map;
2135     ostr.flush();
2136     EXPECT_EQ(out,
2137               "---\n"
2138               "{ str1: This is str1, \n"
2139               "  str2: This is str2, \n"
2140               "  str3: This is str3 }\n"
2141               "...\n");
2142     out.clear();
2143
2144     yout << Seq;
2145     ostr.flush();
2146     EXPECT_EQ(out,
2147               "---\n"
2148               "[ This is str1, \n"
2149               "  This is str2, \n"
2150               "  This is str3 ]\n"
2151               "...\n");
2152     out.clear();
2153   }
2154   {
2155     // 25 will allow the second field to be output on the first line.
2156     Output yout(ostr, nullptr, 25);
2157
2158     yout << Map;
2159     ostr.flush();
2160     EXPECT_EQ(out,
2161               "---\n"
2162               "{ str1: This is str1, str2: This is str2, \n"
2163               "  str3: This is str3 }\n"
2164               "...\n");
2165     out.clear();
2166
2167     yout << Seq;
2168     ostr.flush();
2169     EXPECT_EQ(out,
2170               "---\n"
2171               "[ This is str1, This is str2, \n"
2172               "  This is str3 ]\n"
2173               "...\n");
2174     out.clear();
2175   }
2176   {
2177     // 0 means no wrapping.
2178     Output yout(ostr, nullptr, 0);
2179
2180     yout << Map;
2181     ostr.flush();
2182     EXPECT_EQ(out,
2183               "---\n"
2184               "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n"
2185               "...\n");
2186     out.clear();
2187
2188     yout << Seq;
2189     ostr.flush();
2190     EXPECT_EQ(out,
2191               "---\n"
2192               "[ This is str1, This is str2, This is str3 ]\n"
2193               "...\n");
2194     out.clear();
2195   }
2196 }