blob: 5cf0e9d0f5b35fbca1580be826344d8c0404ed20 [file] [log] [blame]
Nick Kledzikf60a9272012-12-12 20:46:15 +00001//===- 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
Nick Kledzikf60a9272012-12-12 20:46:15 +000010#include "llvm/ADT/Twine.h"
11#include "llvm/Support/Casting.h"
Zachary Turner4fbf61d2016-06-07 19:32:09 +000012#include "llvm/Support/Endian.h"
Nick Kledzikf60a9272012-12-12 20:46:15 +000013#include "llvm/Support/Format.h"
14#include "llvm/Support/YAMLTraits.h"
15#include "gtest/gtest.h"
16
Nick Kledzikf60a9272012-12-12 20:46:15 +000017using llvm::yaml::Input;
18using llvm::yaml::Output;
19using llvm::yaml::IO;
20using llvm::yaml::MappingTraits;
21using llvm::yaml::MappingNormalization;
22using llvm::yaml::ScalarTraits;
23using llvm::yaml::Hex8;
24using llvm::yaml::Hex16;
25using llvm::yaml::Hex32;
26using llvm::yaml::Hex64;
27
28
Nick Kledzik7cd45f22013-11-21 00:28:07 +000029
30
31static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
32}
33
34
35
Nick Kledzikf60a9272012-12-12 20:46:15 +000036//===----------------------------------------------------------------------===//
37// Test MappingTraits
38//===----------------------------------------------------------------------===//
39
40struct FooBar {
41 int foo;
42 int bar;
43};
44typedef std::vector<FooBar> FooBarSequence;
45
46LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
47
Justin Bogner64d2cdf2015-03-02 17:26:43 +000048struct FooBarContainer {
49 FooBarSequence fbs;
50};
Nick Kledzikf60a9272012-12-12 20:46:15 +000051
52namespace llvm {
53namespace yaml {
54 template <>
55 struct MappingTraits<FooBar> {
56 static void mapping(IO &io, FooBar& fb) {
57 io.mapRequired("foo", fb.foo);
58 io.mapRequired("bar", fb.bar);
59 }
60 };
Justin Bogner64d2cdf2015-03-02 17:26:43 +000061
62 template <> struct MappingTraits<FooBarContainer> {
63 static void mapping(IO &io, FooBarContainer &fb) {
64 io.mapRequired("fbs", fb.fbs);
65 }
66 };
Nick Kledzikf60a9272012-12-12 20:46:15 +000067}
68}
69
70
71//
72// Test the reading of a yaml mapping
73//
74TEST(YAMLIO, TestMapRead) {
75 FooBar doc;
Alexander Kornienko681e37c2013-11-18 15:50:04 +000076 {
77 Input yin("---\nfoo: 3\nbar: 5\n...\n");
78 yin >> doc;
Nick Kledzikf60a9272012-12-12 20:46:15 +000079
Alexander Kornienko681e37c2013-11-18 15:50:04 +000080 EXPECT_FALSE(yin.error());
81 EXPECT_EQ(doc.foo, 3);
82 EXPECT_EQ(doc.bar, 5);
83 }
84
85 {
86 Input yin("{foo: 3, bar: 5}");
87 yin >> doc;
88
89 EXPECT_FALSE(yin.error());
90 EXPECT_EQ(doc.foo, 3);
91 EXPECT_EQ(doc.bar, 5);
92 }
Nick Kledzikf60a9272012-12-12 20:46:15 +000093}
94
Rafael Espindolaa97373f2014-08-08 13:58:00 +000095TEST(YAMLIO, TestMalformedMapRead) {
96 FooBar doc;
97 Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages);
98 yin >> doc;
99 EXPECT_TRUE(!!yin.error());
100}
101
Nick Kledzikf60a9272012-12-12 20:46:15 +0000102//
103// Test the reading of a yaml sequence of mappings
104//
105TEST(YAMLIO, TestSequenceMapRead) {
106 FooBarSequence seq;
107 Input yin("---\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n");
108 yin >> seq;
109
110 EXPECT_FALSE(yin.error());
111 EXPECT_EQ(seq.size(), 2UL);
112 FooBar& map1 = seq[0];
113 FooBar& map2 = seq[1];
114 EXPECT_EQ(map1.foo, 3);
115 EXPECT_EQ(map1.bar, 5);
116 EXPECT_EQ(map2.foo, 7);
117 EXPECT_EQ(map2.bar, 9);
118}
119
Justin Bogner64d2cdf2015-03-02 17:26:43 +0000120//
121// Test the reading of a map containing a yaml sequence of mappings
122//
123TEST(YAMLIO, TestContainerSequenceMapRead) {
124 {
125 FooBarContainer cont;
126 Input yin2("---\nfbs:\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n");
127 yin2 >> cont;
128
129 EXPECT_FALSE(yin2.error());
130 EXPECT_EQ(cont.fbs.size(), 2UL);
131 EXPECT_EQ(cont.fbs[0].foo, 3);
132 EXPECT_EQ(cont.fbs[0].bar, 5);
133 EXPECT_EQ(cont.fbs[1].foo, 7);
134 EXPECT_EQ(cont.fbs[1].bar, 9);
135 }
136
137 {
138 FooBarContainer cont;
139 Input yin("---\nfbs:\n...\n");
140 yin >> cont;
141 // Okay: Empty node represents an empty array.
142 EXPECT_FALSE(yin.error());
143 EXPECT_EQ(cont.fbs.size(), 0UL);
144 }
145
146 {
147 FooBarContainer cont;
148 Input yin("---\nfbs: !!null null\n...\n");
149 yin >> cont;
150 // Okay: null represents an empty array.
151 EXPECT_FALSE(yin.error());
152 EXPECT_EQ(cont.fbs.size(), 0UL);
153 }
154
155 {
156 FooBarContainer cont;
157 Input yin("---\nfbs: ~\n...\n");
158 yin >> cont;
159 // Okay: null represents an empty array.
160 EXPECT_FALSE(yin.error());
161 EXPECT_EQ(cont.fbs.size(), 0UL);
162 }
163
164 {
165 FooBarContainer cont;
166 Input yin("---\nfbs: null\n...\n");
167 yin >> cont;
168 // Okay: null represents an empty array.
169 EXPECT_FALSE(yin.error());
170 EXPECT_EQ(cont.fbs.size(), 0UL);
171 }
172}
173
174//
175// Test the reading of a map containing a malformed yaml sequence
176//
177TEST(YAMLIO, TestMalformedContainerSequenceMapRead) {
178 {
179 FooBarContainer cont;
180 Input yin("---\nfbs:\n foo: 3\n bar: 5\n...\n", nullptr,
181 suppressErrorMessages);
182 yin >> cont;
183 // Error: fbs is not a sequence.
184 EXPECT_TRUE(!!yin.error());
185 EXPECT_EQ(cont.fbs.size(), 0UL);
186 }
187
188 {
189 FooBarContainer cont;
190 Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages);
191 yin >> cont;
192 // This should be an error.
193 EXPECT_TRUE(!!yin.error());
194 EXPECT_EQ(cont.fbs.size(), 0UL);
195 }
196}
Nick Kledzikf60a9272012-12-12 20:46:15 +0000197
198//
199// Test writing then reading back a sequence of mappings
200//
201TEST(YAMLIO, TestSequenceMapWriteAndRead) {
202 std::string intermediate;
203 {
204 FooBar entry1;
205 entry1.foo = 10;
206 entry1.bar = -3;
207 FooBar entry2;
208 entry2.foo = 257;
209 entry2.bar = 0;
210 FooBarSequence seq;
211 seq.push_back(entry1);
212 seq.push_back(entry2);
213
214 llvm::raw_string_ostream ostr(intermediate);
215 Output yout(ostr);
216 yout << seq;
217 }
218
219 {
220 Input yin(intermediate);
221 FooBarSequence seq2;
222 yin >> seq2;
223
224 EXPECT_FALSE(yin.error());
225 EXPECT_EQ(seq2.size(), 2UL);
226 FooBar& map1 = seq2[0];
227 FooBar& map2 = seq2[1];
228 EXPECT_EQ(map1.foo, 10);
229 EXPECT_EQ(map1.bar, -3);
230 EXPECT_EQ(map2.foo, 257);
231 EXPECT_EQ(map2.bar, 0);
232 }
233}
234
235
236//===----------------------------------------------------------------------===//
237// Test built-in types
238//===----------------------------------------------------------------------===//
239
240struct BuiltInTypes {
241 llvm::StringRef str;
John Thompson48e018a2013-11-19 17:28:21 +0000242 std::string stdstr;
Nick Kledzikf60a9272012-12-12 20:46:15 +0000243 uint64_t u64;
244 uint32_t u32;
245 uint16_t u16;
246 uint8_t u8;
247 bool b;
248 int64_t s64;
249 int32_t s32;
250 int16_t s16;
251 int8_t s8;
252 float f;
253 double d;
254 Hex8 h8;
255 Hex16 h16;
256 Hex32 h32;
257 Hex64 h64;
258};
259
260namespace llvm {
261namespace yaml {
262 template <>
263 struct MappingTraits<BuiltInTypes> {
264 static void mapping(IO &io, BuiltInTypes& bt) {
265 io.mapRequired("str", bt.str);
John Thompson48e018a2013-11-19 17:28:21 +0000266 io.mapRequired("stdstr", bt.stdstr);
Nick Kledzikf60a9272012-12-12 20:46:15 +0000267 io.mapRequired("u64", bt.u64);
268 io.mapRequired("u32", bt.u32);
269 io.mapRequired("u16", bt.u16);
270 io.mapRequired("u8", bt.u8);
271 io.mapRequired("b", bt.b);
272 io.mapRequired("s64", bt.s64);
273 io.mapRequired("s32", bt.s32);
274 io.mapRequired("s16", bt.s16);
275 io.mapRequired("s8", bt.s8);
276 io.mapRequired("f", bt.f);
277 io.mapRequired("d", bt.d);
278 io.mapRequired("h8", bt.h8);
279 io.mapRequired("h16", bt.h16);
280 io.mapRequired("h32", bt.h32);
281 io.mapRequired("h64", bt.h64);
282 }
283 };
284}
285}
286
287
288//
289// Test the reading of all built-in scalar conversions
290//
291TEST(YAMLIO, TestReadBuiltInTypes) {
292 BuiltInTypes map;
293 Input yin("---\n"
294 "str: hello there\n"
John Thompson48e018a2013-11-19 17:28:21 +0000295 "stdstr: hello where?\n"
Nick Kledzikf60a9272012-12-12 20:46:15 +0000296 "u64: 5000000000\n"
297 "u32: 4000000000\n"
298 "u16: 65000\n"
299 "u8: 255\n"
300 "b: false\n"
301 "s64: -5000000000\n"
302 "s32: -2000000000\n"
303 "s16: -32000\n"
304 "s8: -127\n"
305 "f: 137.125\n"
306 "d: -2.8625\n"
307 "h8: 0xFF\n"
308 "h16: 0x8765\n"
309 "h32: 0xFEDCBA98\n"
310 "h64: 0xFEDCBA9876543210\n"
311 "...\n");
312 yin >> map;
313
314 EXPECT_FALSE(yin.error());
315 EXPECT_TRUE(map.str.equals("hello there"));
John Thompson48e018a2013-11-19 17:28:21 +0000316 EXPECT_TRUE(map.stdstr == "hello where?");
Nick Kledzikf60a9272012-12-12 20:46:15 +0000317 EXPECT_EQ(map.u64, 5000000000ULL);
Nick Kledzikbed953d2012-12-17 22:11:17 +0000318 EXPECT_EQ(map.u32, 4000000000U);
Nick Kledzikf60a9272012-12-12 20:46:15 +0000319 EXPECT_EQ(map.u16, 65000);
320 EXPECT_EQ(map.u8, 255);
321 EXPECT_EQ(map.b, false);
322 EXPECT_EQ(map.s64, -5000000000LL);
323 EXPECT_EQ(map.s32, -2000000000L);
324 EXPECT_EQ(map.s16, -32000);
325 EXPECT_EQ(map.s8, -127);
326 EXPECT_EQ(map.f, 137.125);
327 EXPECT_EQ(map.d, -2.8625);
328 EXPECT_EQ(map.h8, Hex8(255));
329 EXPECT_EQ(map.h16, Hex16(0x8765));
330 EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
331 EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
332}
333
334
335//
336// Test writing then reading back all built-in scalar types
337//
338TEST(YAMLIO, TestReadWriteBuiltInTypes) {
339 std::string intermediate;
340 {
341 BuiltInTypes map;
342 map.str = "one two";
John Thompson48e018a2013-11-19 17:28:21 +0000343 map.stdstr = "three four";
Nick Kledzikbed953d2012-12-17 22:11:17 +0000344 map.u64 = 6000000000ULL;
345 map.u32 = 3000000000U;
Nick Kledzikf60a9272012-12-12 20:46:15 +0000346 map.u16 = 50000;
347 map.u8 = 254;
348 map.b = true;
Nick Kledzikbed953d2012-12-17 22:11:17 +0000349 map.s64 = -6000000000LL;
Nick Kledzikf60a9272012-12-12 20:46:15 +0000350 map.s32 = -2000000000;
351 map.s16 = -32000;
352 map.s8 = -128;
353 map.f = 3.25;
354 map.d = -2.8625;
355 map.h8 = 254;
356 map.h16 = 50000;
Nick Kledzikbed953d2012-12-17 22:11:17 +0000357 map.h32 = 3000000000U;
Nick Kledzikf60a9272012-12-12 20:46:15 +0000358 map.h64 = 6000000000LL;
359
360 llvm::raw_string_ostream ostr(intermediate);
361 Output yout(ostr);
362 yout << map;
363 }
364
365 {
366 Input yin(intermediate);
367 BuiltInTypes map;
368 yin >> map;
369
370 EXPECT_FALSE(yin.error());
371 EXPECT_TRUE(map.str.equals("one two"));
John Thompson48e018a2013-11-19 17:28:21 +0000372 EXPECT_TRUE(map.stdstr == "three four");
Nick Kledzikf60a9272012-12-12 20:46:15 +0000373 EXPECT_EQ(map.u64, 6000000000ULL);
Nick Kledzikbed953d2012-12-17 22:11:17 +0000374 EXPECT_EQ(map.u32, 3000000000U);
Nick Kledzikf60a9272012-12-12 20:46:15 +0000375 EXPECT_EQ(map.u16, 50000);
376 EXPECT_EQ(map.u8, 254);
377 EXPECT_EQ(map.b, true);
378 EXPECT_EQ(map.s64, -6000000000LL);
379 EXPECT_EQ(map.s32, -2000000000L);
380 EXPECT_EQ(map.s16, -32000);
381 EXPECT_EQ(map.s8, -128);
382 EXPECT_EQ(map.f, 3.25);
383 EXPECT_EQ(map.d, -2.8625);
384 EXPECT_EQ(map.h8, Hex8(254));
385 EXPECT_EQ(map.h16, Hex16(50000));
Nick Kledzikbed953d2012-12-17 22:11:17 +0000386 EXPECT_EQ(map.h32, Hex32(3000000000U));
Nick Kledzikf60a9272012-12-12 20:46:15 +0000387 EXPECT_EQ(map.h64, Hex64(6000000000LL));
388 }
389}
390
Zachary Turner4fbf61d2016-06-07 19:32:09 +0000391//===----------------------------------------------------------------------===//
392// Test endian-aware types
393//===----------------------------------------------------------------------===//
394
395struct EndianTypes {
396 typedef llvm::support::detail::packed_endian_specific_integral<
397 float, llvm::support::little, llvm::support::unaligned>
398 ulittle_float;
399 typedef llvm::support::detail::packed_endian_specific_integral<
400 double, llvm::support::little, llvm::support::unaligned>
401 ulittle_double;
402
403 llvm::support::ulittle64_t u64;
404 llvm::support::ulittle32_t u32;
405 llvm::support::ulittle16_t u16;
406 llvm::support::little64_t s64;
407 llvm::support::little32_t s32;
408 llvm::support::little16_t s16;
409 ulittle_float f;
410 ulittle_double d;
411};
412
413namespace llvm {
414namespace yaml {
415template <> struct MappingTraits<EndianTypes> {
416 static void mapping(IO &io, EndianTypes &et) {
417 io.mapRequired("u64", et.u64);
418 io.mapRequired("u32", et.u32);
419 io.mapRequired("u16", et.u16);
420 io.mapRequired("s64", et.s64);
421 io.mapRequired("s32", et.s32);
422 io.mapRequired("s16", et.s16);
423 io.mapRequired("f", et.f);
424 io.mapRequired("d", et.d);
425 }
426};
427}
428}
429
430//
431// Test the reading of all endian scalar conversions
432//
433TEST(YAMLIO, TestReadEndianTypes) {
434 EndianTypes map;
435 Input yin("---\n"
436 "u64: 5000000000\n"
437 "u32: 4000000000\n"
438 "u16: 65000\n"
439 "s64: -5000000000\n"
440 "s32: -2000000000\n"
441 "s16: -32000\n"
442 "f: 3.25\n"
443 "d: -2.8625\n"
444 "...\n");
445 yin >> map;
446
447 EXPECT_FALSE(yin.error());
448 EXPECT_EQ(map.u64, 5000000000ULL);
449 EXPECT_EQ(map.u32, 4000000000U);
450 EXPECT_EQ(map.u16, 65000);
451 EXPECT_EQ(map.s64, -5000000000LL);
452 EXPECT_EQ(map.s32, -2000000000L);
453 EXPECT_EQ(map.s16, -32000);
454 EXPECT_EQ(map.f, 3.25f);
455 EXPECT_EQ(map.d, -2.8625);
456}
457
458//
459// Test writing then reading back all endian-aware scalar types
460//
461TEST(YAMLIO, TestReadWriteEndianTypes) {
462 std::string intermediate;
463 {
464 EndianTypes map;
465 map.u64 = 6000000000ULL;
466 map.u32 = 3000000000U;
467 map.u16 = 50000;
468 map.s64 = -6000000000LL;
469 map.s32 = -2000000000;
470 map.s16 = -32000;
471 map.f = 3.25f;
472 map.d = -2.8625;
473
474 llvm::raw_string_ostream ostr(intermediate);
475 Output yout(ostr);
476 yout << map;
477 }
478
479 {
480 Input yin(intermediate);
481 EndianTypes map;
482 yin >> map;
483
484 EXPECT_FALSE(yin.error());
485 EXPECT_EQ(map.u64, 6000000000ULL);
486 EXPECT_EQ(map.u32, 3000000000U);
487 EXPECT_EQ(map.u16, 50000);
488 EXPECT_EQ(map.s64, -6000000000LL);
489 EXPECT_EQ(map.s32, -2000000000L);
490 EXPECT_EQ(map.s16, -32000);
491 EXPECT_EQ(map.f, 3.25f);
492 EXPECT_EQ(map.d, -2.8625);
493 }
494}
495
Rui Ueyama106eded2013-09-11 04:00:08 +0000496struct StringTypes {
497 llvm::StringRef str1;
498 llvm::StringRef str2;
499 llvm::StringRef str3;
500 llvm::StringRef str4;
501 llvm::StringRef str5;
David Majnemer97d8ee32014-04-09 17:04:27 +0000502 llvm::StringRef str6;
David Majnemer77880332014-04-10 07:37:33 +0000503 llvm::StringRef str7;
504 llvm::StringRef str8;
505 llvm::StringRef str9;
506 llvm::StringRef str10;
507 llvm::StringRef str11;
John Thompson48e018a2013-11-19 17:28:21 +0000508 std::string stdstr1;
509 std::string stdstr2;
510 std::string stdstr3;
511 std::string stdstr4;
512 std::string stdstr5;
David Majnemer97d8ee32014-04-09 17:04:27 +0000513 std::string stdstr6;
David Majnemer77880332014-04-10 07:37:33 +0000514 std::string stdstr7;
515 std::string stdstr8;
516 std::string stdstr9;
517 std::string stdstr10;
518 std::string stdstr11;
Rui Ueyama106eded2013-09-11 04:00:08 +0000519};
Nick Kledzikf60a9272012-12-12 20:46:15 +0000520
Rui Ueyama106eded2013-09-11 04:00:08 +0000521namespace llvm {
522namespace yaml {
523 template <>
524 struct MappingTraits<StringTypes> {
525 static void mapping(IO &io, StringTypes& st) {
526 io.mapRequired("str1", st.str1);
527 io.mapRequired("str2", st.str2);
528 io.mapRequired("str3", st.str3);
529 io.mapRequired("str4", st.str4);
530 io.mapRequired("str5", st.str5);
David Majnemer97d8ee32014-04-09 17:04:27 +0000531 io.mapRequired("str6", st.str6);
David Majnemer77880332014-04-10 07:37:33 +0000532 io.mapRequired("str7", st.str7);
533 io.mapRequired("str8", st.str8);
534 io.mapRequired("str9", st.str9);
535 io.mapRequired("str10", st.str10);
536 io.mapRequired("str11", st.str11);
John Thompson48e018a2013-11-19 17:28:21 +0000537 io.mapRequired("stdstr1", st.stdstr1);
538 io.mapRequired("stdstr2", st.stdstr2);
539 io.mapRequired("stdstr3", st.stdstr3);
540 io.mapRequired("stdstr4", st.stdstr4);
541 io.mapRequired("stdstr5", st.stdstr5);
David Majnemer97d8ee32014-04-09 17:04:27 +0000542 io.mapRequired("stdstr6", st.stdstr6);
David Majnemer77880332014-04-10 07:37:33 +0000543 io.mapRequired("stdstr7", st.stdstr7);
544 io.mapRequired("stdstr8", st.stdstr8);
545 io.mapRequired("stdstr9", st.stdstr9);
546 io.mapRequired("stdstr10", st.stdstr10);
547 io.mapRequired("stdstr11", st.stdstr11);
Rui Ueyama106eded2013-09-11 04:00:08 +0000548 }
549 };
550}
551}
552
553TEST(YAMLIO, TestReadWriteStringTypes) {
554 std::string intermediate;
555 {
556 StringTypes map;
557 map.str1 = "'aaa";
558 map.str2 = "\"bbb";
559 map.str3 = "`ccc";
560 map.str4 = "@ddd";
561 map.str5 = "";
David Majnemer97d8ee32014-04-09 17:04:27 +0000562 map.str6 = "0000000004000000";
David Majnemer77880332014-04-10 07:37:33 +0000563 map.str7 = "true";
564 map.str8 = "FALSE";
565 map.str9 = "~";
566 map.str10 = "0.2e20";
567 map.str11 = "0x30";
John Thompson48e018a2013-11-19 17:28:21 +0000568 map.stdstr1 = "'eee";
569 map.stdstr2 = "\"fff";
570 map.stdstr3 = "`ggg";
571 map.stdstr4 = "@hhh";
572 map.stdstr5 = "";
David Majnemer97d8ee32014-04-09 17:04:27 +0000573 map.stdstr6 = "0000000004000000";
David Majnemer77880332014-04-10 07:37:33 +0000574 map.stdstr7 = "true";
575 map.stdstr8 = "FALSE";
576 map.stdstr9 = "~";
577 map.stdstr10 = "0.2e20";
578 map.stdstr11 = "0x30";
Rui Ueyama106eded2013-09-11 04:00:08 +0000579
580 llvm::raw_string_ostream ostr(intermediate);
581 Output yout(ostr);
582 yout << map;
583 }
584
585 llvm::StringRef flowOut(intermediate);
586 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
587 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
588 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
589 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
590 EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
David Majnemer97d8ee32014-04-09 17:04:27 +0000591 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
David Majnemer77880332014-04-10 07:37:33 +0000592 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
593 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
594 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
595 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
596 EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
John Thompson48e018a2013-11-19 17:28:21 +0000597 EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
598 EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
599 EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
600 EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
601 EXPECT_NE(std::string::npos, flowOut.find("''\n"));
David Majnemer97d8ee32014-04-09 17:04:27 +0000602 EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
Rui Ueyama106eded2013-09-11 04:00:08 +0000603
604 {
605 Input yin(intermediate);
606 StringTypes map;
607 yin >> map;
608
609 EXPECT_FALSE(yin.error());
610 EXPECT_TRUE(map.str1.equals("'aaa"));
611 EXPECT_TRUE(map.str2.equals("\"bbb"));
612 EXPECT_TRUE(map.str3.equals("`ccc"));
613 EXPECT_TRUE(map.str4.equals("@ddd"));
614 EXPECT_TRUE(map.str5.equals(""));
David Majnemer97d8ee32014-04-09 17:04:27 +0000615 EXPECT_TRUE(map.str6.equals("0000000004000000"));
John Thompson48e018a2013-11-19 17:28:21 +0000616 EXPECT_TRUE(map.stdstr1 == "'eee");
617 EXPECT_TRUE(map.stdstr2 == "\"fff");
618 EXPECT_TRUE(map.stdstr3 == "`ggg");
619 EXPECT_TRUE(map.stdstr4 == "@hhh");
620 EXPECT_TRUE(map.stdstr5 == "");
David Majnemer97d8ee32014-04-09 17:04:27 +0000621 EXPECT_TRUE(map.stdstr6 == "0000000004000000");
Rui Ueyama106eded2013-09-11 04:00:08 +0000622 }
623}
Nick Kledzikf60a9272012-12-12 20:46:15 +0000624
625//===----------------------------------------------------------------------===//
626// Test ScalarEnumerationTraits
627//===----------------------------------------------------------------------===//
628
629enum Colors {
630 cRed,
631 cBlue,
632 cGreen,
633 cYellow
634};
635
636struct ColorMap {
637 Colors c1;
638 Colors c2;
639 Colors c3;
640 Colors c4;
641 Colors c5;
642 Colors c6;
643};
644
645namespace llvm {
646namespace yaml {
647 template <>
648 struct ScalarEnumerationTraits<Colors> {
649 static void enumeration(IO &io, Colors &value) {
650 io.enumCase(value, "red", cRed);
651 io.enumCase(value, "blue", cBlue);
652 io.enumCase(value, "green", cGreen);
653 io.enumCase(value, "yellow",cYellow);
654 }
655 };
656 template <>
657 struct MappingTraits<ColorMap> {
658 static void mapping(IO &io, ColorMap& c) {
659 io.mapRequired("c1", c.c1);
660 io.mapRequired("c2", c.c2);
661 io.mapRequired("c3", c.c3);
662 io.mapOptional("c4", c.c4, cBlue); // supplies default
663 io.mapOptional("c5", c.c5, cYellow); // supplies default
664 io.mapOptional("c6", c.c6, cRed); // supplies default
665 }
666 };
667}
668}
669
670
671//
672// Test reading enumerated scalars
673//
674TEST(YAMLIO, TestEnumRead) {
675 ColorMap map;
676 Input yin("---\n"
677 "c1: blue\n"
678 "c2: red\n"
679 "c3: green\n"
680 "c5: yellow\n"
681 "...\n");
682 yin >> map;
683
684 EXPECT_FALSE(yin.error());
685 EXPECT_EQ(cBlue, map.c1);
686 EXPECT_EQ(cRed, map.c2);
687 EXPECT_EQ(cGreen, map.c3);
688 EXPECT_EQ(cBlue, map.c4); // tests default
689 EXPECT_EQ(cYellow,map.c5); // tests overridden
690 EXPECT_EQ(cRed, map.c6); // tests default
691}
692
693
694
695//===----------------------------------------------------------------------===//
696// Test ScalarBitSetTraits
697//===----------------------------------------------------------------------===//
698
699enum MyFlags {
700 flagNone = 0,
701 flagBig = 1 << 0,
702 flagFlat = 1 << 1,
703 flagRound = 1 << 2,
704 flagPointy = 1 << 3
705};
706inline MyFlags operator|(MyFlags a, MyFlags b) {
707 return static_cast<MyFlags>(
708 static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
709}
710
711struct FlagsMap {
712 MyFlags f1;
713 MyFlags f2;
714 MyFlags f3;
715 MyFlags f4;
716};
717
718
719namespace llvm {
720namespace yaml {
721 template <>
722 struct ScalarBitSetTraits<MyFlags> {
723 static void bitset(IO &io, MyFlags &value) {
724 io.bitSetCase(value, "big", flagBig);
725 io.bitSetCase(value, "flat", flagFlat);
726 io.bitSetCase(value, "round", flagRound);
727 io.bitSetCase(value, "pointy",flagPointy);
728 }
729 };
730 template <>
731 struct MappingTraits<FlagsMap> {
732 static void mapping(IO &io, FlagsMap& c) {
733 io.mapRequired("f1", c.f1);
734 io.mapRequired("f2", c.f2);
735 io.mapRequired("f3", c.f3);
736 io.mapOptional("f4", c.f4, MyFlags(flagRound));
737 }
738 };
739}
740}
741
742
743//
744// Test reading flow sequence representing bit-mask values
745//
746TEST(YAMLIO, TestFlagsRead) {
747 FlagsMap map;
748 Input yin("---\n"
749 "f1: [ big ]\n"
750 "f2: [ round, flat ]\n"
751 "f3: []\n"
752 "...\n");
753 yin >> map;
754
755 EXPECT_FALSE(yin.error());
756 EXPECT_EQ(flagBig, map.f1);
757 EXPECT_EQ(flagRound|flagFlat, map.f2);
758 EXPECT_EQ(flagNone, map.f3); // check empty set
759 EXPECT_EQ(flagRound, map.f4); // check optional key
760}
761
762
763//
764// Test writing then reading back bit-mask values
765//
766TEST(YAMLIO, TestReadWriteFlags) {
767 std::string intermediate;
768 {
769 FlagsMap map;
770 map.f1 = flagBig;
771 map.f2 = flagRound | flagFlat;
772 map.f3 = flagNone;
773 map.f4 = flagNone;
774
775 llvm::raw_string_ostream ostr(intermediate);
776 Output yout(ostr);
777 yout << map;
778 }
779
780 {
781 Input yin(intermediate);
782 FlagsMap map2;
783 yin >> map2;
784
785 EXPECT_FALSE(yin.error());
786 EXPECT_EQ(flagBig, map2.f1);
787 EXPECT_EQ(flagRound|flagFlat, map2.f2);
788 EXPECT_EQ(flagNone, map2.f3);
789 //EXPECT_EQ(flagRound, map2.f4); // check optional key
790 }
791}
792
793
794
795//===----------------------------------------------------------------------===//
796// Test ScalarTraits
797//===----------------------------------------------------------------------===//
798
799struct MyCustomType {
800 int length;
801 int width;
802};
803
804struct MyCustomTypeMap {
805 MyCustomType f1;
806 MyCustomType f2;
807 int f3;
808};
809
810
811namespace llvm {
812namespace yaml {
813 template <>
814 struct MappingTraits<MyCustomTypeMap> {
815 static void mapping(IO &io, MyCustomTypeMap& s) {
816 io.mapRequired("f1", s.f1);
817 io.mapRequired("f2", s.f2);
818 io.mapRequired("f3", s.f3);
819 }
820 };
821 // MyCustomType is formatted as a yaml scalar. A value of
822 // {length=3, width=4} would be represented in yaml as "3 by 4".
823 template<>
824 struct ScalarTraits<MyCustomType> {
825 static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
826 out << llvm::format("%d by %d", value.length, value.width);
827 }
828 static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
829 size_t byStart = scalar.find("by");
830 if ( byStart != StringRef::npos ) {
831 StringRef lenStr = scalar.slice(0, byStart);
832 lenStr = lenStr.rtrim();
833 if ( lenStr.getAsInteger(0, value.length) ) {
834 return "malformed length";
835 }
836 StringRef widthStr = scalar.drop_front(byStart+2);
837 widthStr = widthStr.ltrim();
838 if ( widthStr.getAsInteger(0, value.width) ) {
839 return "malformed width";
840 }
841 return StringRef();
842 }
843 else {
844 return "malformed by";
845 }
846 }
David Majnemer77880332014-04-10 07:37:33 +0000847 static bool mustQuote(StringRef) { return true; }
Nick Kledzikf60a9272012-12-12 20:46:15 +0000848 };
849}
850}
851
852
853//
854// Test writing then reading back custom values
855//
856TEST(YAMLIO, TestReadWriteMyCustomType) {
857 std::string intermediate;
858 {
859 MyCustomTypeMap map;
860 map.f1.length = 1;
861 map.f1.width = 4;
862 map.f2.length = 100;
863 map.f2.width = 400;
864 map.f3 = 10;
865
866 llvm::raw_string_ostream ostr(intermediate);
867 Output yout(ostr);
868 yout << map;
869 }
870
871 {
872 Input yin(intermediate);
873 MyCustomTypeMap map2;
874 yin >> map2;
875
876 EXPECT_FALSE(yin.error());
877 EXPECT_EQ(1, map2.f1.length);
878 EXPECT_EQ(4, map2.f1.width);
879 EXPECT_EQ(100, map2.f2.length);
880 EXPECT_EQ(400, map2.f2.width);
881 EXPECT_EQ(10, map2.f3);
882 }
883}
884
885
886//===----------------------------------------------------------------------===//
Alex Lorenz68e787b2015-05-14 23:08:22 +0000887// Test BlockScalarTraits
888//===----------------------------------------------------------------------===//
889
890struct MultilineStringType {
891 std::string str;
892};
893
894struct MultilineStringTypeMap {
895 MultilineStringType name;
896 MultilineStringType description;
897 MultilineStringType ingredients;
898 MultilineStringType recipes;
899 MultilineStringType warningLabels;
900 MultilineStringType documentation;
901 int price;
902};
903
904namespace llvm {
905namespace yaml {
906 template <>
907 struct MappingTraits<MultilineStringTypeMap> {
908 static void mapping(IO &io, MultilineStringTypeMap& s) {
909 io.mapRequired("name", s.name);
910 io.mapRequired("description", s.description);
911 io.mapRequired("ingredients", s.ingredients);
912 io.mapRequired("recipes", s.recipes);
913 io.mapRequired("warningLabels", s.warningLabels);
914 io.mapRequired("documentation", s.documentation);
915 io.mapRequired("price", s.price);
916 }
917 };
918
919 // MultilineStringType is formatted as a yaml block literal scalar. A value of
920 // "Hello\nWorld" would be represented in yaml as
921 // |
922 // Hello
923 // World
924 template <>
925 struct BlockScalarTraits<MultilineStringType> {
926 static void output(const MultilineStringType &value, void *ctxt,
927 llvm::raw_ostream &out) {
928 out << value.str;
929 }
930 static StringRef input(StringRef scalar, void *ctxt,
931 MultilineStringType &value) {
932 value.str = scalar.str();
933 return StringRef();
934 }
935 };
936}
937}
938
939LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
940
941//
942// Test writing then reading back custom values
943//
944TEST(YAMLIO, TestReadWriteMultilineStringType) {
945 std::string intermediate;
946 {
947 MultilineStringTypeMap map;
948 map.name.str = "An Item";
949 map.description.str = "Hello\nWorld";
950 map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n";
951 map.recipes.str = "\n\nTest 1\n\n\n";
952 map.warningLabels.str = "";
953 map.documentation.str = "\n\n";
954 map.price = 350;
955
956 llvm::raw_string_ostream ostr(intermediate);
957 Output yout(ostr);
958 yout << map;
959 }
960 {
961 Input yin(intermediate);
962 MultilineStringTypeMap map2;
963 yin >> map2;
964
965 EXPECT_FALSE(yin.error());
966 EXPECT_EQ(map2.name.str, "An Item\n");
967 EXPECT_EQ(map2.description.str, "Hello\nWorld\n");
968 EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n");
969 EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n");
970 EXPECT_TRUE(map2.warningLabels.str.empty());
971 EXPECT_TRUE(map2.documentation.str.empty());
972 EXPECT_EQ(map2.price, 350);
973 }
974}
975
976//
977// Test writing then reading back custom values
978//
979TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
980 std::string intermediate;
981 {
982 std::vector<MultilineStringType> documents;
983 MultilineStringType doc;
984 doc.str = "Hello\nWorld";
985 documents.push_back(doc);
986
987 llvm::raw_string_ostream ostr(intermediate);
988 Output yout(ostr);
989 yout << documents;
990
991 // Verify that the block scalar header was written out on the same line
992 // as the document marker.
993 EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |"));
994 }
995 {
996 Input yin(intermediate);
997 std::vector<MultilineStringType> documents2;
998 yin >> documents2;
999
1000 EXPECT_FALSE(yin.error());
1001 EXPECT_EQ(documents2.size(), size_t(1));
1002 EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
1003 }
1004}
1005
1006TEST(YAMLIO, TestReadWriteBlockScalarValue) {
1007 std::string intermediate;
1008 {
1009 MultilineStringType doc;
1010 doc.str = "Just a block\nscalar doc";
1011
1012 llvm::raw_string_ostream ostr(intermediate);
1013 Output yout(ostr);
1014 yout << doc;
1015 }
1016 {
1017 Input yin(intermediate);
1018 MultilineStringType doc;
1019 yin >> doc;
1020
1021 EXPECT_FALSE(yin.error());
1022 EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
1023 }
1024}
1025
1026//===----------------------------------------------------------------------===//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001027// Test flow sequences
1028//===----------------------------------------------------------------------===//
1029
1030LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
1031LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
Richard Smithd0c0c132017-06-30 20:56:57 +00001032LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, MyString)
1033LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyString)
Nick Kledzikf60a9272012-12-12 20:46:15 +00001034
1035namespace llvm {
1036namespace yaml {
1037 template<>
1038 struct ScalarTraits<MyNumber> {
1039 static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
1040 out << value;
1041 }
1042
1043 static StringRef input(StringRef scalar, void *, MyNumber &value) {
David Blaikieb088ff62012-12-12 22:14:32 +00001044 long long n;
Nick Kledzikf60a9272012-12-12 20:46:15 +00001045 if ( getAsSignedInteger(scalar, 0, n) )
1046 return "invalid number";
1047 value = n;
1048 return StringRef();
1049 }
David Majnemer77880332014-04-10 07:37:33 +00001050
1051 static bool mustQuote(StringRef) { return false; }
Nick Kledzikf60a9272012-12-12 20:46:15 +00001052 };
Richard Smithd0c0c132017-06-30 20:56:57 +00001053
1054 template <> struct ScalarTraits<MyString> {
1055 using Impl = ScalarTraits<StringRef>;
1056 static void output(const MyString &V, void *Ctx, raw_ostream &OS) {
1057 Impl::output(V, Ctx, OS);
1058 }
1059 static StringRef input(StringRef S, void *Ctx, MyString &V) {
1060 return Impl::input(S, Ctx, V.value);
1061 }
1062 static bool mustQuote(StringRef S) { return Impl::mustQuote(S); }
1063 };
Nick Kledzikf60a9272012-12-12 20:46:15 +00001064}
1065}
1066
1067struct NameAndNumbers {
1068 llvm::StringRef name;
Richard Smithd0c0c132017-06-30 20:56:57 +00001069 std::vector<MyString> strings;
Nick Kledzikf60a9272012-12-12 20:46:15 +00001070 std::vector<MyNumber> single;
1071 std::vector<MyNumber> numbers;
1072};
1073
1074namespace llvm {
1075namespace yaml {
1076 template <>
1077 struct MappingTraits<NameAndNumbers> {
1078 static void mapping(IO &io, NameAndNumbers& nn) {
1079 io.mapRequired("name", nn.name);
1080 io.mapRequired("strings", nn.strings);
1081 io.mapRequired("single", nn.single);
1082 io.mapRequired("numbers", nn.numbers);
1083 }
1084 };
1085}
1086}
1087
Alex Lorenz42e91fa2015-05-01 18:34:25 +00001088typedef std::vector<MyNumber> MyNumberFlowSequence;
1089
1090LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
1091
1092struct NameAndNumbersFlow {
1093 llvm::StringRef name;
1094 std::vector<MyNumberFlowSequence> sequenceOfNumbers;
1095};
1096
1097namespace llvm {
1098namespace yaml {
1099 template <>
1100 struct MappingTraits<NameAndNumbersFlow> {
1101 static void mapping(IO &io, NameAndNumbersFlow& nn) {
1102 io.mapRequired("name", nn.name);
1103 io.mapRequired("sequenceOfNumbers", nn.sequenceOfNumbers);
1104 }
1105 };
1106}
1107}
Nick Kledzikf60a9272012-12-12 20:46:15 +00001108
1109//
1110// Test writing then reading back custom values
1111//
1112TEST(YAMLIO, TestReadWriteMyFlowSequence) {
1113 std::string intermediate;
1114 {
1115 NameAndNumbers map;
1116 map.name = "hello";
1117 map.strings.push_back(llvm::StringRef("one"));
1118 map.strings.push_back(llvm::StringRef("two"));
1119 map.single.push_back(1);
1120 map.numbers.push_back(10);
1121 map.numbers.push_back(-30);
1122 map.numbers.push_back(1024);
1123
1124 llvm::raw_string_ostream ostr(intermediate);
Rui Ueyama38dfffa2013-09-11 00:53:07 +00001125 Output yout(ostr);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001126 yout << map;
Rui Ueyama38dfffa2013-09-11 00:53:07 +00001127
Nick Kledzik11964f22013-01-04 19:32:00 +00001128 // Verify sequences were written in flow style
1129 ostr.flush();
1130 llvm::StringRef flowOut(intermediate);
1131 EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
1132 EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
Nick Kledzikf60a9272012-12-12 20:46:15 +00001133 }
1134
1135 {
1136 Input yin(intermediate);
1137 NameAndNumbers map2;
1138 yin >> map2;
1139
1140 EXPECT_FALSE(yin.error());
1141 EXPECT_TRUE(map2.name.equals("hello"));
1142 EXPECT_EQ(map2.strings.size(), 2UL);
Richard Smithd0c0c132017-06-30 20:56:57 +00001143 EXPECT_TRUE(map2.strings[0].value.equals("one"));
1144 EXPECT_TRUE(map2.strings[1].value.equals("two"));
Nick Kledzikf60a9272012-12-12 20:46:15 +00001145 EXPECT_EQ(map2.single.size(), 1UL);
1146 EXPECT_EQ(1, map2.single[0]);
1147 EXPECT_EQ(map2.numbers.size(), 3UL);
1148 EXPECT_EQ(10, map2.numbers[0]);
1149 EXPECT_EQ(-30, map2.numbers[1]);
1150 EXPECT_EQ(1024, map2.numbers[2]);
1151 }
1152}
1153
1154
Alex Lorenz42e91fa2015-05-01 18:34:25 +00001155//
1156// Test writing then reading back a sequence of flow sequences.
1157//
1158TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
1159 std::string intermediate;
1160 {
1161 NameAndNumbersFlow map;
1162 map.name = "hello";
1163 MyNumberFlowSequence single = { 0 };
1164 MyNumberFlowSequence numbers = { 12, 1, -512 };
1165 map.sequenceOfNumbers.push_back(single);
1166 map.sequenceOfNumbers.push_back(numbers);
1167 map.sequenceOfNumbers.push_back(MyNumberFlowSequence());
1168
1169 llvm::raw_string_ostream ostr(intermediate);
1170 Output yout(ostr);
1171 yout << map;
1172
1173 // Verify sequences were written in flow style
1174 // and that the parent sequence used '-'.
1175 ostr.flush();
1176 llvm::StringRef flowOut(intermediate);
1177 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]"));
1178 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]"));
1179 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ ]"));
1180 }
1181
1182 {
1183 Input yin(intermediate);
1184 NameAndNumbersFlow map2;
1185 yin >> map2;
1186
1187 EXPECT_FALSE(yin.error());
1188 EXPECT_TRUE(map2.name.equals("hello"));
1189 EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL);
1190 EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL);
1191 EXPECT_EQ(0, map2.sequenceOfNumbers[0][0]);
1192 EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL);
1193 EXPECT_EQ(12, map2.sequenceOfNumbers[1][0]);
1194 EXPECT_EQ(1, map2.sequenceOfNumbers[1][1]);
1195 EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]);
1196 EXPECT_TRUE(map2.sequenceOfNumbers[2].empty());
1197 }
1198}
1199
Nick Kledzikf60a9272012-12-12 20:46:15 +00001200//===----------------------------------------------------------------------===//
1201// Test normalizing/denormalizing
1202//===----------------------------------------------------------------------===//
1203
1204LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
1205
1206typedef std::vector<TotalSeconds> SecondsSequence;
1207
Nick Kledzik11964f22013-01-04 19:32:00 +00001208LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
Nick Kledzikf60a9272012-12-12 20:46:15 +00001209
1210
1211namespace llvm {
1212namespace yaml {
1213 template <>
1214 struct MappingTraits<TotalSeconds> {
1215
1216 class NormalizedSeconds {
1217 public:
1218 NormalizedSeconds(IO &io)
1219 : hours(0), minutes(0), seconds(0) {
1220 }
1221 NormalizedSeconds(IO &, TotalSeconds &secs)
1222 : hours(secs/3600),
1223 minutes((secs - (hours*3600))/60),
1224 seconds(secs % 60) {
1225 }
1226 TotalSeconds denormalize(IO &) {
1227 return TotalSeconds(hours*3600 + minutes*60 + seconds);
1228 }
1229
1230 uint32_t hours;
1231 uint8_t minutes;
1232 uint8_t seconds;
1233 };
1234
1235 static void mapping(IO &io, TotalSeconds &secs) {
1236 MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
1237
1238 io.mapOptional("hours", keys->hours, (uint32_t)0);
1239 io.mapOptional("minutes", keys->minutes, (uint8_t)0);
1240 io.mapRequired("seconds", keys->seconds);
1241 }
1242 };
1243}
1244}
1245
1246
1247//
1248// Test the reading of a yaml sequence of mappings
1249//
1250TEST(YAMLIO, TestReadMySecondsSequence) {
1251 SecondsSequence seq;
1252 Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n");
1253 yin >> seq;
1254
1255 EXPECT_FALSE(yin.error());
1256 EXPECT_EQ(seq.size(), 2UL);
1257 EXPECT_EQ(seq[0], 3605U);
1258 EXPECT_EQ(seq[1], 59U);
1259}
1260
1261
1262//
1263// Test writing then reading back custom values
1264//
1265TEST(YAMLIO, TestReadWriteMySecondsSequence) {
1266 std::string intermediate;
1267 {
1268 SecondsSequence seq;
1269 seq.push_back(4000);
1270 seq.push_back(500);
1271 seq.push_back(59);
1272
1273 llvm::raw_string_ostream ostr(intermediate);
1274 Output yout(ostr);
1275 yout << seq;
1276 }
1277 {
1278 Input yin(intermediate);
1279 SecondsSequence seq2;
1280 yin >> seq2;
1281
1282 EXPECT_FALSE(yin.error());
1283 EXPECT_EQ(seq2.size(), 3UL);
1284 EXPECT_EQ(seq2[0], 4000U);
1285 EXPECT_EQ(seq2[1], 500U);
1286 EXPECT_EQ(seq2[2], 59U);
1287 }
1288}
1289
1290
1291//===----------------------------------------------------------------------===//
1292// Test dynamic typing
1293//===----------------------------------------------------------------------===//
1294
1295enum AFlags {
1296 a1,
1297 a2,
1298 a3
1299};
1300
1301enum BFlags {
1302 b1,
1303 b2,
1304 b3
1305};
1306
1307enum Kind {
1308 kindA,
1309 kindB
1310};
1311
1312struct KindAndFlags {
1313 KindAndFlags() : kind(kindA), flags(0) { }
1314 KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
1315 Kind kind;
1316 uint32_t flags;
1317};
1318
1319typedef std::vector<KindAndFlags> KindAndFlagsSequence;
1320
Nick Kledzik11964f22013-01-04 19:32:00 +00001321LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
Nick Kledzikf60a9272012-12-12 20:46:15 +00001322
1323namespace llvm {
1324namespace yaml {
1325 template <>
1326 struct ScalarEnumerationTraits<AFlags> {
1327 static void enumeration(IO &io, AFlags &value) {
1328 io.enumCase(value, "a1", a1);
1329 io.enumCase(value, "a2", a2);
1330 io.enumCase(value, "a3", a3);
1331 }
1332 };
1333 template <>
1334 struct ScalarEnumerationTraits<BFlags> {
1335 static void enumeration(IO &io, BFlags &value) {
1336 io.enumCase(value, "b1", b1);
1337 io.enumCase(value, "b2", b2);
1338 io.enumCase(value, "b3", b3);
1339 }
1340 };
1341 template <>
1342 struct ScalarEnumerationTraits<Kind> {
1343 static void enumeration(IO &io, Kind &value) {
1344 io.enumCase(value, "A", kindA);
1345 io.enumCase(value, "B", kindB);
1346 }
1347 };
1348 template <>
1349 struct MappingTraits<KindAndFlags> {
1350 static void mapping(IO &io, KindAndFlags& kf) {
1351 io.mapRequired("kind", kf.kind);
Dmitri Gribenkoba9d1b52013-01-10 21:10:44 +00001352 // Type of "flags" field varies depending on "kind" field.
David Greene4162c2d2013-01-10 18:17:54 +00001353 // Use memcpy here to avoid breaking strict aliasing rules.
Dmitri Gribenkoba9d1b52013-01-10 21:10:44 +00001354 if (kf.kind == kindA) {
Dmitri Gribenko7b4fb9a2013-01-10 21:21:32 +00001355 AFlags aflags = static_cast<AFlags>(kf.flags);
David Greene4162c2d2013-01-10 18:17:54 +00001356 io.mapRequired("flags", aflags);
Dmitri Gribenko7b4fb9a2013-01-10 21:21:32 +00001357 kf.flags = aflags;
Dmitri Gribenkoba9d1b52013-01-10 21:10:44 +00001358 } else {
Dmitri Gribenko7b4fb9a2013-01-10 21:21:32 +00001359 BFlags bflags = static_cast<BFlags>(kf.flags);
David Greene4162c2d2013-01-10 18:17:54 +00001360 io.mapRequired("flags", bflags);
Dmitri Gribenko7b4fb9a2013-01-10 21:21:32 +00001361 kf.flags = bflags;
David Greene4162c2d2013-01-10 18:17:54 +00001362 }
Nick Kledzikf60a9272012-12-12 20:46:15 +00001363 }
1364 };
1365}
1366}
1367
1368
1369//
1370// Test the reading of a yaml sequence dynamic types
1371//
1372TEST(YAMLIO, TestReadKindAndFlagsSequence) {
1373 KindAndFlagsSequence seq;
1374 Input yin("---\n - kind: A\n flags: a2\n - kind: B\n flags: b1\n...\n");
1375 yin >> seq;
1376
1377 EXPECT_FALSE(yin.error());
1378 EXPECT_EQ(seq.size(), 2UL);
1379 EXPECT_EQ(seq[0].kind, kindA);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001380 EXPECT_EQ(seq[0].flags, (uint32_t)a2);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001381 EXPECT_EQ(seq[1].kind, kindB);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001382 EXPECT_EQ(seq[1].flags, (uint32_t)b1);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001383}
1384
1385//
1386// Test writing then reading back dynamic types
1387//
1388TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
1389 std::string intermediate;
1390 {
1391 KindAndFlagsSequence seq;
1392 seq.push_back(KindAndFlags(kindA,a1));
1393 seq.push_back(KindAndFlags(kindB,b1));
1394 seq.push_back(KindAndFlags(kindA,a2));
1395 seq.push_back(KindAndFlags(kindB,b2));
1396 seq.push_back(KindAndFlags(kindA,a3));
1397
1398 llvm::raw_string_ostream ostr(intermediate);
1399 Output yout(ostr);
1400 yout << seq;
1401 }
1402 {
1403 Input yin(intermediate);
1404 KindAndFlagsSequence seq2;
1405 yin >> seq2;
1406
1407 EXPECT_FALSE(yin.error());
1408 EXPECT_EQ(seq2.size(), 5UL);
1409 EXPECT_EQ(seq2[0].kind, kindA);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001410 EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001411 EXPECT_EQ(seq2[1].kind, kindB);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001412 EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001413 EXPECT_EQ(seq2[2].kind, kindA);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001414 EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001415 EXPECT_EQ(seq2[3].kind, kindB);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001416 EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001417 EXPECT_EQ(seq2[4].kind, kindA);
Nick Kledzik52bfd382012-12-17 20:43:53 +00001418 EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001419 }
1420}
1421
1422
1423//===----------------------------------------------------------------------===//
1424// Test document list
1425//===----------------------------------------------------------------------===//
1426
1427struct FooBarMap {
1428 int foo;
1429 int bar;
1430};
1431typedef std::vector<FooBarMap> FooBarMapDocumentList;
1432
1433LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
1434
1435
1436namespace llvm {
1437namespace yaml {
1438 template <>
1439 struct MappingTraits<FooBarMap> {
1440 static void mapping(IO &io, FooBarMap& fb) {
1441 io.mapRequired("foo", fb.foo);
1442 io.mapRequired("bar", fb.bar);
1443 }
1444 };
1445}
1446}
1447
1448
1449//
1450// Test the reading of a yaml mapping
1451//
1452TEST(YAMLIO, TestDocRead) {
1453 FooBarMap doc;
1454 Input yin("---\nfoo: 3\nbar: 5\n...\n");
1455 yin >> doc;
1456
1457 EXPECT_FALSE(yin.error());
1458 EXPECT_EQ(doc.foo, 3);
1459 EXPECT_EQ(doc.bar,5);
1460}
1461
1462
1463
1464//
1465// Test writing then reading back a sequence of mappings
1466//
1467TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
1468 std::string intermediate;
1469 {
1470 FooBarMap doc1;
1471 doc1.foo = 10;
1472 doc1.bar = -3;
1473 FooBarMap doc2;
1474 doc2.foo = 257;
1475 doc2.bar = 0;
1476 std::vector<FooBarMap> docList;
1477 docList.push_back(doc1);
1478 docList.push_back(doc2);
1479
1480 llvm::raw_string_ostream ostr(intermediate);
1481 Output yout(ostr);
1482 yout << docList;
1483 }
1484
1485
1486 {
1487 Input yin(intermediate);
1488 std::vector<FooBarMap> docList2;
1489 yin >> docList2;
1490
1491 EXPECT_FALSE(yin.error());
1492 EXPECT_EQ(docList2.size(), 2UL);
1493 FooBarMap& map1 = docList2[0];
1494 FooBarMap& map2 = docList2[1];
1495 EXPECT_EQ(map1.foo, 10);
1496 EXPECT_EQ(map1.bar, -3);
1497 EXPECT_EQ(map2.foo, 257);
1498 EXPECT_EQ(map2.bar, 0);
1499 }
1500}
1501
Nick Kledzik1e6033c2013-11-14 00:59:59 +00001502//===----------------------------------------------------------------------===//
1503// Test document tags
1504//===----------------------------------------------------------------------===//
1505
1506struct MyDouble {
1507 MyDouble() : value(0.0) { }
1508 MyDouble(double x) : value(x) { }
1509 double value;
1510};
1511
Nick Kledzik4a9f00d2013-11-14 03:03:05 +00001512LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
Nick Kledzik1e6033c2013-11-14 00:59:59 +00001513
1514
1515namespace llvm {
1516namespace yaml {
1517 template <>
1518 struct MappingTraits<MyDouble> {
1519 static void mapping(IO &io, MyDouble &d) {
1520 if (io.mapTag("!decimal", true)) {
1521 mappingDecimal(io, d);
1522 } else if (io.mapTag("!fraction")) {
1523 mappingFraction(io, d);
1524 }
1525 }
1526 static void mappingDecimal(IO &io, MyDouble &d) {
1527 io.mapRequired("value", d.value);
1528 }
1529 static void mappingFraction(IO &io, MyDouble &d) {
1530 double num, denom;
1531 io.mapRequired("numerator", num);
1532 io.mapRequired("denominator", denom);
1533 // convert fraction to double
1534 d.value = num/denom;
1535 }
1536 };
1537 }
1538}
1539
1540
1541//
1542// Test the reading of two different tagged yaml documents.
1543//
1544TEST(YAMLIO, TestTaggedDocuments) {
1545 std::vector<MyDouble> docList;
1546 Input yin("--- !decimal\nvalue: 3.0\n"
1547 "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n");
1548 yin >> docList;
1549 EXPECT_FALSE(yin.error());
1550 EXPECT_EQ(docList.size(), 2UL);
1551 EXPECT_EQ(docList[0].value, 3.0);
1552 EXPECT_EQ(docList[1].value, 4.5);
1553}
1554
1555
1556
1557//
1558// Test writing then reading back tagged documents
1559//
1560TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1561 std::string intermediate;
1562 {
1563 MyDouble a(10.25);
1564 MyDouble b(-3.75);
1565 std::vector<MyDouble> docList;
1566 docList.push_back(a);
1567 docList.push_back(b);
1568
1569 llvm::raw_string_ostream ostr(intermediate);
1570 Output yout(ostr);
1571 yout << docList;
1572 }
1573
1574 {
1575 Input yin(intermediate);
1576 std::vector<MyDouble> docList2;
1577 yin >> docList2;
1578
1579 EXPECT_FALSE(yin.error());
1580 EXPECT_EQ(docList2.size(), 2UL);
1581 EXPECT_EQ(docList2[0].value, 10.25);
1582 EXPECT_EQ(docList2[1].value, -3.75);
1583 }
1584}
1585
1586
Nick Kledzik7cd45f22013-11-21 00:28:07 +00001587//===----------------------------------------------------------------------===//
1588// Test mapping validation
1589//===----------------------------------------------------------------------===//
1590
1591struct MyValidation {
1592 double value;
1593};
1594
1595LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
1596
1597namespace llvm {
1598namespace yaml {
1599 template <>
1600 struct MappingTraits<MyValidation> {
1601 static void mapping(IO &io, MyValidation &d) {
1602 io.mapRequired("value", d.value);
1603 }
1604 static StringRef validate(IO &io, MyValidation &d) {
1605 if (d.value < 0)
1606 return "negative value";
1607 return StringRef();
1608 }
1609 };
1610 }
1611}
1612
1613
1614//
1615// Test that validate() is called and complains about the negative value.
1616//
1617TEST(YAMLIO, TestValidatingInput) {
1618 std::vector<MyValidation> docList;
1619 Input yin("--- \nvalue: 3.0\n"
1620 "--- \nvalue: -1.0\n...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001621 nullptr, suppressErrorMessages);
Nick Kledzik7cd45f22013-11-21 00:28:07 +00001622 yin >> docList;
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001623 EXPECT_TRUE(!!yin.error());
Nick Kledzik7cd45f22013-11-21 00:28:07 +00001624}
1625
Alex Lorenzb1225082015-05-04 20:11:40 +00001626//===----------------------------------------------------------------------===//
1627// Test flow mapping
1628//===----------------------------------------------------------------------===//
1629
1630struct FlowFooBar {
1631 int foo;
1632 int bar;
1633
1634 FlowFooBar() : foo(0), bar(0) {}
1635 FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
1636};
1637
1638typedef std::vector<FlowFooBar> FlowFooBarSequence;
1639
1640LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
1641
1642struct FlowFooBarDoc {
1643 FlowFooBar attribute;
1644 FlowFooBarSequence seq;
1645};
1646
1647namespace llvm {
1648namespace yaml {
1649 template <>
1650 struct MappingTraits<FlowFooBar> {
1651 static void mapping(IO &io, FlowFooBar &fb) {
1652 io.mapRequired("foo", fb.foo);
1653 io.mapRequired("bar", fb.bar);
1654 }
1655
1656 static const bool flow = true;
1657 };
1658
1659 template <>
1660 struct MappingTraits<FlowFooBarDoc> {
1661 static void mapping(IO &io, FlowFooBarDoc &fb) {
1662 io.mapRequired("attribute", fb.attribute);
1663 io.mapRequired("seq", fb.seq);
1664 }
1665 };
1666}
1667}
1668
1669//
1670// Test writing then reading back custom mappings
1671//
1672TEST(YAMLIO, TestReadWriteMyFlowMapping) {
1673 std::string intermediate;
1674 {
1675 FlowFooBarDoc doc;
1676 doc.attribute = FlowFooBar(42, 907);
1677 doc.seq.push_back(FlowFooBar(1, 2));
1678 doc.seq.push_back(FlowFooBar(0, 0));
1679 doc.seq.push_back(FlowFooBar(-1, 1024));
1680
1681 llvm::raw_string_ostream ostr(intermediate);
1682 Output yout(ostr);
1683 yout << doc;
1684
1685 // Verify that mappings were written in flow style
1686 ostr.flush();
1687 llvm::StringRef flowOut(intermediate);
1688 EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
1689 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
1690 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
1691 EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
1692 }
1693
1694 {
1695 Input yin(intermediate);
1696 FlowFooBarDoc doc2;
1697 yin >> doc2;
1698
1699 EXPECT_FALSE(yin.error());
1700 EXPECT_EQ(doc2.attribute.foo, 42);
1701 EXPECT_EQ(doc2.attribute.bar, 907);
1702 EXPECT_EQ(doc2.seq.size(), 3UL);
1703 EXPECT_EQ(doc2.seq[0].foo, 1);
1704 EXPECT_EQ(doc2.seq[0].bar, 2);
1705 EXPECT_EQ(doc2.seq[1].foo, 0);
1706 EXPECT_EQ(doc2.seq[1].bar, 0);
1707 EXPECT_EQ(doc2.seq[2].foo, -1);
1708 EXPECT_EQ(doc2.seq[2].bar, 1024);
1709 }
1710}
Nick Kledzikf60a9272012-12-12 20:46:15 +00001711
1712//===----------------------------------------------------------------------===//
1713// Test error handling
1714//===----------------------------------------------------------------------===//
1715
Nick Kledzikf60a9272012-12-12 20:46:15 +00001716//
1717// Test error handling of unknown enumerated scalar
1718//
1719TEST(YAMLIO, TestColorsReadError) {
1720 ColorMap map;
1721 Input yin("---\n"
1722 "c1: blue\n"
1723 "c2: purple\n"
1724 "c3: green\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001725 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001726 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001727 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001728 yin >> map;
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001729 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001730}
1731
1732
1733//
1734// Test error handling of flow sequence with unknown value
1735//
1736TEST(YAMLIO, TestFlagsReadError) {
1737 FlagsMap map;
1738 Input yin("---\n"
1739 "f1: [ big ]\n"
1740 "f2: [ round, hollow ]\n"
1741 "f3: []\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001742 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001743 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001744 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001745 yin >> map;
1746
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001747 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001748}
1749
1750
1751//
1752// Test error handling reading built-in uint8_t type
1753//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001754TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1755 std::vector<uint8_t> seq;
1756 Input yin("---\n"
1757 "- 255\n"
1758 "- 0\n"
1759 "- 257\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001760 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001761 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001762 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001763 yin >> seq;
1764
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001765 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001766}
1767
1768
1769//
1770// Test error handling reading built-in uint16_t type
1771//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001772TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1773 std::vector<uint16_t> seq;
1774 Input yin("---\n"
1775 "- 65535\n"
1776 "- 0\n"
1777 "- 66000\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001778 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001779 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001780 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001781 yin >> seq;
1782
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001783 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001784}
1785
1786
1787//
1788// Test error handling reading built-in uint32_t type
1789//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001790TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1791 std::vector<uint32_t> seq;
1792 Input yin("---\n"
1793 "- 4000000000\n"
1794 "- 0\n"
1795 "- 5000000000\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001796 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001797 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001798 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001799 yin >> seq;
1800
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001801 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001802}
1803
1804
1805//
1806// Test error handling reading built-in uint64_t type
1807//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001808TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1809 std::vector<uint64_t> seq;
1810 Input yin("---\n"
1811 "- 18446744073709551615\n"
1812 "- 0\n"
1813 "- 19446744073709551615\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001814 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001815 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001816 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001817 yin >> seq;
1818
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001819 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001820}
1821
1822
1823//
1824// Test error handling reading built-in int8_t type
1825//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001826TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1827 std::vector<int8_t> seq;
1828 Input yin("---\n"
1829 "- -128\n"
1830 "- 0\n"
1831 "- 127\n"
1832 "- 128\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001833 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001834 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001835 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001836 yin >> seq;
1837
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001838 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001839}
1840
1841//
1842// Test error handling reading built-in int8_t type
1843//
1844TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1845 std::vector<int8_t> seq;
1846 Input yin("---\n"
1847 "- -128\n"
1848 "- 0\n"
1849 "- 127\n"
1850 "- -129\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001851 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001852 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001853 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001854 yin >> seq;
1855
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001856 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001857}
1858
1859
1860//
1861// Test error handling reading built-in int16_t type
1862//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001863TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1864 std::vector<int16_t> seq;
1865 Input yin("---\n"
1866 "- 32767\n"
1867 "- 0\n"
1868 "- -32768\n"
1869 "- -32769\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001870 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001871 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001872 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001873 yin >> seq;
1874
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001875 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001876}
1877
1878
1879//
1880// Test error handling reading built-in int16_t type
1881//
1882TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1883 std::vector<int16_t> seq;
1884 Input yin("---\n"
1885 "- 32767\n"
1886 "- 0\n"
1887 "- -32768\n"
1888 "- 32768\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001889 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001890 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001891 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001892 yin >> seq;
1893
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001894 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001895}
1896
1897
1898//
1899// Test error handling reading built-in int32_t type
1900//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001901TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1902 std::vector<int32_t> seq;
1903 Input yin("---\n"
1904 "- 2147483647\n"
1905 "- 0\n"
1906 "- -2147483648\n"
1907 "- -2147483649\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001908 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001909 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001910 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001911 yin >> seq;
1912
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001913 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001914}
1915
1916//
1917// Test error handling reading built-in int32_t type
1918//
1919TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1920 std::vector<int32_t> seq;
1921 Input yin("---\n"
1922 "- 2147483647\n"
1923 "- 0\n"
1924 "- -2147483648\n"
1925 "- 2147483649\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001926 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001927 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001928 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001929 yin >> seq;
1930
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001931 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001932}
1933
1934
1935//
1936// Test error handling reading built-in int64_t type
1937//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001938TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1939 std::vector<int64_t> seq;
1940 Input yin("---\n"
1941 "- -9223372036854775808\n"
1942 "- 0\n"
1943 "- 9223372036854775807\n"
1944 "- -9223372036854775809\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001945 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001946 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001947 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001948 yin >> seq;
1949
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001950 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001951}
1952
1953//
1954// Test error handling reading built-in int64_t type
1955//
1956TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1957 std::vector<int64_t> seq;
1958 Input yin("---\n"
1959 "- -9223372036854775808\n"
1960 "- 0\n"
1961 "- 9223372036854775807\n"
1962 "- 9223372036854775809\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001963 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001964 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001965 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001966 yin >> seq;
1967
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001968 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001969}
1970
1971//
1972// Test error handling reading built-in float type
1973//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001974TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1975 std::vector<float> seq;
1976 Input yin("---\n"
1977 "- 0.0\n"
1978 "- 1000.1\n"
1979 "- -123.456\n"
1980 "- 1.2.3\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001981 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00001982 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001983 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00001984 yin >> seq;
1985
Rafael Espindolad9a25d82014-06-03 04:42:24 +00001986 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00001987}
1988
1989//
1990// Test error handling reading built-in float type
1991//
Nick Kledzikf60a9272012-12-12 20:46:15 +00001992TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1993 std::vector<double> seq;
1994 Input yin("---\n"
1995 "- 0.0\n"
1996 "- 1000.1\n"
1997 "- -123.456\n"
1998 "- 1.2.3\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00001999 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00002000 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002001 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00002002 yin >> seq;
2003
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002004 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00002005}
2006
2007//
2008// Test error handling reading built-in Hex8 type
2009//
2010LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
2011TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
2012 std::vector<Hex8> seq;
2013 Input yin("---\n"
2014 "- 0x12\n"
2015 "- 0xFE\n"
2016 "- 0x123\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002017 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00002018 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002019 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00002020 yin >> seq;
2021
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002022 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00002023}
2024
2025
2026//
2027// Test error handling reading built-in Hex16 type
2028//
2029LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
2030TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
2031 std::vector<Hex16> seq;
2032 Input yin("---\n"
2033 "- 0x0012\n"
2034 "- 0xFEFF\n"
2035 "- 0x12345\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002036 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00002037 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002038 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00002039 yin >> seq;
2040
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002041 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00002042}
2043
2044//
2045// Test error handling reading built-in Hex32 type
2046//
2047LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
2048TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
2049 std::vector<Hex32> seq;
2050 Input yin("---\n"
2051 "- 0x0012\n"
2052 "- 0xFEFF0000\n"
2053 "- 0x1234556789\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002054 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00002055 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002056 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00002057 yin >> seq;
2058
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002059 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00002060}
2061
2062//
2063// Test error handling reading built-in Hex64 type
2064//
2065LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
2066TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
2067 std::vector<Hex64> seq;
2068 Input yin("---\n"
2069 "- 0x0012\n"
2070 "- 0xFFEEDDCCBBAA9988\n"
2071 "- 0x12345567890ABCDEF0\n"
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002072 "...\n",
Craig Topper66f09ad2014-06-08 22:29:17 +00002073 /*Ctxt=*/nullptr,
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002074 suppressErrorMessages);
Nick Kledzikf60a9272012-12-12 20:46:15 +00002075 yin >> seq;
2076
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002077 EXPECT_TRUE(!!yin.error());
Nick Kledzikf60a9272012-12-12 20:46:15 +00002078}
2079
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002080TEST(YAMLIO, TestMalformedMapFailsGracefully) {
2081 FooBar doc;
2082 {
2083 // We pass the suppressErrorMessages handler to handle the error
2084 // message generated in the constructor of Input.
Craig Topper66f09ad2014-06-08 22:29:17 +00002085 Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002086 yin >> doc;
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002087 EXPECT_TRUE(!!yin.error());
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002088 }
2089
2090 {
Craig Topper66f09ad2014-06-08 22:29:17 +00002091 Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002092 yin >> doc;
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002093 EXPECT_TRUE(!!yin.error());
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002094 }
2095}
2096
Aaron Ballman0e63e532013-08-15 23:17:53 +00002097struct OptionalTest {
2098 std::vector<int> Numbers;
2099};
2100
2101struct OptionalTestSeq {
2102 std::vector<OptionalTest> Tests;
2103};
2104
Aaron Ballman381f59f2013-08-16 01:53:58 +00002105LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
Aaron Ballman0e63e532013-08-15 23:17:53 +00002106namespace llvm {
2107namespace yaml {
2108 template <>
2109 struct MappingTraits<OptionalTest> {
2110 static void mapping(IO& IO, OptionalTest &OT) {
2111 IO.mapOptional("Numbers", OT.Numbers);
2112 }
2113 };
2114
2115 template <>
2116 struct MappingTraits<OptionalTestSeq> {
2117 static void mapping(IO &IO, OptionalTestSeq &OTS) {
2118 IO.mapOptional("Tests", OTS.Tests);
2119 }
2120 };
2121}
2122}
2123
2124TEST(YAMLIO, SequenceElideTest) {
2125 // Test that writing out a purely optional structure with its fields set to
2126 // default followed by other data is properly read back in.
2127 OptionalTestSeq Seq;
2128 OptionalTest One, Two, Three, Four;
2129 int N[] = {1, 2, 3};
2130 Three.Numbers.assign(N, N + 3);
2131 Seq.Tests.push_back(One);
2132 Seq.Tests.push_back(Two);
2133 Seq.Tests.push_back(Three);
2134 Seq.Tests.push_back(Four);
2135
2136 std::string intermediate;
2137 {
2138 llvm::raw_string_ostream ostr(intermediate);
2139 Output yout(ostr);
2140 yout << Seq;
2141 }
2142
2143 Input yin(intermediate);
2144 OptionalTestSeq Seq2;
2145 yin >> Seq2;
Rui Ueyama38dfffa2013-09-11 00:53:07 +00002146
Aaron Ballman0e63e532013-08-15 23:17:53 +00002147 EXPECT_FALSE(yin.error());
2148
2149 EXPECT_EQ(4UL, Seq2.Tests.size());
2150
2151 EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
2152 EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
2153
2154 EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
2155 EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
2156 EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
2157
2158 EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
2159}
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002160
2161TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
2162 FooBar doc;
2163 Input yin("");
2164 yin >> doc;
Rafael Espindolad9a25d82014-06-03 04:42:24 +00002165 EXPECT_TRUE(!!yin.error());
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002166}
2167
2168TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
2169 OptionalTest doc;
2170 Input yin("");
2171 yin >> doc;
2172 EXPECT_FALSE(yin.error());
2173}
2174
2175TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
2176 std::vector<uint8_t> seq;
Craig Topper66f09ad2014-06-08 22:29:17 +00002177 Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
Alexander Kornienko681e37c2013-11-18 15:50:04 +00002178 yin >> seq;
2179
2180 EXPECT_FALSE(yin.error());
2181 EXPECT_TRUE(seq.empty());
2182}
Frederic Riss4939e6a2015-05-29 17:56:28 +00002183
2184struct FlowMap {
2185 llvm::StringRef str1, str2, str3;
2186 FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3)
2187 : str1(str1), str2(str2), str3(str3) {}
2188};
2189
Frederic Riss3733c032015-05-29 18:14:55 +00002190struct FlowSeq {
2191 llvm::StringRef str;
2192 FlowSeq(llvm::StringRef S) : str(S) {}
2193 FlowSeq() = default;
2194};
2195
Frederic Riss4939e6a2015-05-29 17:56:28 +00002196namespace llvm {
2197namespace yaml {
2198 template <>
2199 struct MappingTraits<FlowMap> {
2200 static void mapping(IO &io, FlowMap &fm) {
2201 io.mapRequired("str1", fm.str1);
2202 io.mapRequired("str2", fm.str2);
2203 io.mapRequired("str3", fm.str3);
2204 }
2205
2206 static const bool flow = true;
2207 };
Frederic Riss4939e6a2015-05-29 17:56:28 +00002208
2209template <>
2210struct ScalarTraits<FlowSeq> {
2211 static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
2212 out << value.str;
2213 }
2214 static StringRef input(StringRef scalar, void*, FlowSeq &value) {
2215 value.str = scalar;
2216 return "";
2217 }
2218
2219 static bool mustQuote(StringRef S) { return false; }
2220};
Frederic Riss3733c032015-05-29 18:14:55 +00002221}
2222}
Frederic Riss4939e6a2015-05-29 17:56:28 +00002223
2224LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
2225
2226TEST(YAMLIO, TestWrapFlow) {
2227 std::string out;
2228 llvm::raw_string_ostream ostr(out);
2229 FlowMap Map("This is str1", "This is str2", "This is str3");
2230 std::vector<FlowSeq> Seq;
2231 Seq.emplace_back("This is str1");
2232 Seq.emplace_back("This is str2");
2233 Seq.emplace_back("This is str3");
2234
2235 {
2236 // 20 is just bellow the total length of the first mapping field.
2237 // We should wreap at every element.
2238 Output yout(ostr, nullptr, 15);
2239
2240 yout << Map;
2241 ostr.flush();
2242 EXPECT_EQ(out,
2243 "---\n"
2244 "{ str1: This is str1, \n"
2245 " str2: This is str2, \n"
2246 " str3: This is str3 }\n"
2247 "...\n");
2248 out.clear();
2249
2250 yout << Seq;
2251 ostr.flush();
2252 EXPECT_EQ(out,
2253 "---\n"
2254 "[ This is str1, \n"
2255 " This is str2, \n"
2256 " This is str3 ]\n"
2257 "...\n");
2258 out.clear();
2259 }
2260 {
2261 // 25 will allow the second field to be output on the first line.
2262 Output yout(ostr, nullptr, 25);
2263
2264 yout << Map;
2265 ostr.flush();
2266 EXPECT_EQ(out,
2267 "---\n"
2268 "{ str1: This is str1, str2: This is str2, \n"
2269 " str3: This is str3 }\n"
2270 "...\n");
2271 out.clear();
2272
2273 yout << Seq;
2274 ostr.flush();
2275 EXPECT_EQ(out,
2276 "---\n"
2277 "[ This is str1, This is str2, \n"
2278 " This is str3 ]\n"
2279 "...\n");
2280 out.clear();
2281 }
2282 {
2283 // 0 means no wrapping.
2284 Output yout(ostr, nullptr, 0);
2285
2286 yout << Map;
2287 ostr.flush();
2288 EXPECT_EQ(out,
2289 "---\n"
2290 "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n"
2291 "...\n");
2292 out.clear();
2293
2294 yout << Seq;
2295 ostr.flush();
2296 EXPECT_EQ(out,
2297 "---\n"
2298 "[ This is str1, This is str2, This is str3 ]\n"
2299 "...\n");
2300 out.clear();
2301 }
2302}
Zachary Turner35377f82016-09-08 18:22:44 +00002303
2304struct MappingContext {
2305 int A = 0;
2306};
2307struct SimpleMap {
2308 int B = 0;
2309 int C = 0;
2310};
2311
2312struct NestedMap {
2313 NestedMap(MappingContext &Context) : Context(Context) {}
2314 SimpleMap Simple;
2315 MappingContext &Context;
2316};
2317
2318namespace llvm {
2319namespace yaml {
2320template <> struct MappingContextTraits<SimpleMap, MappingContext> {
2321 static void mapping(IO &io, SimpleMap &sm, MappingContext &Context) {
2322 io.mapRequired("B", sm.B);
2323 io.mapRequired("C", sm.C);
2324 ++Context.A;
2325 io.mapRequired("Context", Context.A);
2326 }
2327};
2328
2329template <> struct MappingTraits<NestedMap> {
2330 static void mapping(IO &io, NestedMap &nm) {
2331 io.mapRequired("Simple", nm.Simple, nm.Context);
2332 }
2333};
2334}
2335}
2336
2337TEST(YAMLIO, TestMapWithContext) {
2338 MappingContext Context;
2339 NestedMap Nested(Context);
2340 std::string out;
2341 llvm::raw_string_ostream ostr(out);
2342
2343 Output yout(ostr, nullptr, 15);
2344
2345 yout << Nested;
2346 ostr.flush();
2347 EXPECT_EQ(1, Context.A);
2348 EXPECT_EQ("---\n"
2349 "Simple: \n"
2350 " B: 0\n"
2351 " C: 0\n"
2352 " Context: 1\n"
2353 "...\n",
2354 out);
2355
2356 out.clear();
2357
2358 Nested.Simple.B = 2;
2359 Nested.Simple.C = 3;
2360 yout << Nested;
2361 ostr.flush();
2362 EXPECT_EQ(2, Context.A);
2363 EXPECT_EQ("---\n"
2364 "Simple: \n"
2365 " B: 2\n"
2366 " C: 3\n"
2367 " Context: 2\n"
2368 "...\n",
2369 out);
2370 out.clear();
2371}
Mehdi Amini3ab3fef2016-11-28 21:38:52 +00002372
Peter Collingbourne87dd2ab2017-01-04 03:51:36 +00002373LLVM_YAML_IS_STRING_MAP(int)
2374
2375TEST(YAMLIO, TestCustomMapping) {
2376 std::map<std::string, int> x;
2377 x["foo"] = 1;
2378 x["bar"] = 2;
2379
2380 std::string out;
2381 llvm::raw_string_ostream ostr(out);
2382 Output xout(ostr, nullptr, 0);
2383
2384 xout << x;
2385 ostr.flush();
2386 EXPECT_EQ("---\n"
2387 "bar: 2\n"
2388 "foo: 1\n"
2389 "...\n",
2390 out);
2391
2392 Input yin(out);
2393 std::map<std::string, int> y;
2394 yin >> y;
2395 EXPECT_EQ(2ul, y.size());
2396 EXPECT_EQ(1, y["foo"]);
2397 EXPECT_EQ(2, y["bar"]);
2398}
2399
2400LLVM_YAML_IS_STRING_MAP(FooBar)
2401
2402TEST(YAMLIO, TestCustomMappingStruct) {
2403 std::map<std::string, FooBar> x;
2404 x["foo"].foo = 1;
2405 x["foo"].bar = 2;
2406 x["bar"].foo = 3;
2407 x["bar"].bar = 4;
2408
2409 std::string out;
2410 llvm::raw_string_ostream ostr(out);
2411 Output xout(ostr, nullptr, 0);
2412
2413 xout << x;
2414 ostr.flush();
2415 EXPECT_EQ("---\n"
2416 "bar: \n"
2417 " foo: 3\n"
2418 " bar: 4\n"
2419 "foo: \n"
2420 " foo: 1\n"
2421 " bar: 2\n"
2422 "...\n",
2423 out);
2424
2425 Input yin(out);
2426 std::map<std::string, FooBar> y;
2427 yin >> y;
2428 EXPECT_EQ(2ul, y.size());
2429 EXPECT_EQ(1, y["foo"].foo);
2430 EXPECT_EQ(2, y["foo"].bar);
2431 EXPECT_EQ(3, y["bar"].foo);
2432 EXPECT_EQ(4, y["bar"].bar);
2433}
2434
Mehdi Amini3ab3fef2016-11-28 21:38:52 +00002435TEST(YAMLIO, InvalidInput) {
2436 // polluting 1 value in the sequence
2437 Input yin("---\n- foo: 3\n bar: 5\n1\n- foo: 3\n bar: 5\n...\n");
2438 std::vector<FooBar> Data;
2439 yin >> Data;
2440 EXPECT_TRUE((bool)yin.error());
2441}