spectests.cpp 57.4 KB
Newer Older
Jesse Beder's avatar
Jesse Beder committed
1
#include "spectests.h"
2
#include "specexamples.h"
3
#include "yaml-cpp/yaml.h"
Jesse Beder's avatar
Jesse Beder committed
4
5
6
7
8
#include <fstream>
#include <sstream>
#include <vector>
#include <iostream>

9
#define YAML_ASSERT(cond) do { if(!(cond)) return "  Assert failed: " #cond; } while(false)
10
11
12
13
14
15
#define PARSE(doc, input) \
	std::stringstream stream(input);\
	YAML::Parser parser(stream);\
	YAML::Node doc;\
	parser.GetNextDocument(doc)
#define PARSE_NEXT(doc) parser.GetNextDocument(doc)
16

Jesse Beder's avatar
Jesse Beder committed
17
18
namespace Test {
	namespace Spec {
19
		// 2.1
Jesse Beder's avatar
Jesse Beder committed
20
		TEST SeqScalars() {
Jesse Beder's avatar
Jesse Beder committed
21
22
23
24
			std::string input =
				"- Mark McGwire\n"
				"- Sammy Sosa\n"
				"- Ken Griffey";
25
26

			PARSE(doc, input);
27
			YAML_ASSERT(doc.size() == 3);
28
29
30
			YAML_ASSERT(doc[0].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc[1].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc[2].to<std::string>() == "Ken Griffey");
Jesse Beder's avatar
Jesse Beder committed
31
32
33
			return true;
		}
		
34
		// 2.2
Jesse Beder's avatar
Jesse Beder committed
35
		TEST MappingScalarsToScalars() {
Jesse Beder's avatar
Jesse Beder committed
36
37
38
39
40
			std::string input =
				"hr:  65    # Home runs\n"
				"avg: 0.278 # Batting average\n"
				"rbi: 147   # Runs Batted In";

41
			PARSE(doc, input);
42
			YAML_ASSERT(doc.size() == 3);
43
44
45
			YAML_ASSERT(doc["hr"].to<std::string>() == "65");
			YAML_ASSERT(doc["avg"].to<std::string>() == "0.278");
			YAML_ASSERT(doc["rbi"].to<std::string>() == "147");
Jesse Beder's avatar
Jesse Beder committed
46
47
			return true;
		}
Jesse Beder's avatar
Jesse Beder committed
48
		
49
		// 2.3
Jesse Beder's avatar
Jesse Beder committed
50
51
52
53
54
55
56
57
58
59
		TEST MappingScalarsToSequences() {
			std::string input =
				"american:\n"
				"- Boston Red Sox\n"
				"- Detroit Tigers\n"
				"- New York Yankees\n"
				"national:\n"
				"- New York Mets\n"
				"- Chicago Cubs\n"
				"- Atlanta Braves";
60
61

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
62
63
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["american"].size() == 3);
64
65
66
			YAML_ASSERT(doc["american"][0].to<std::string>() == "Boston Red Sox");
			YAML_ASSERT(doc["american"][1].to<std::string>() == "Detroit Tigers");
			YAML_ASSERT(doc["american"][2].to<std::string>() == "New York Yankees");
Jesse Beder's avatar
Jesse Beder committed
67
			YAML_ASSERT(doc["national"].size() == 3);
68
69
70
			YAML_ASSERT(doc["national"][0].to<std::string>() == "New York Mets");
			YAML_ASSERT(doc["national"][1].to<std::string>() == "Chicago Cubs");
			YAML_ASSERT(doc["national"][2].to<std::string>() == "Atlanta Braves");
Jesse Beder's avatar
Jesse Beder committed
71
72
73
			return true;
		}
		
74
		// 2.4
Jesse Beder's avatar
Jesse Beder committed
75
76
77
78
79
80
81
82
83
84
85
		TEST SequenceOfMappings()
		{
			std::string input =
				"-\n"
				"  name: Mark McGwire\n"
				"  hr:   65\n"
				"  avg:  0.278\n"
				"-\n"
				"  name: Sammy Sosa\n"
				"  hr:   63\n"
				"  avg:  0.288";
86
87

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
88
89
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc[0].size() == 3);
90
91
92
			YAML_ASSERT(doc[0]["name"].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc[0]["hr"].to<std::string>() == "65");
			YAML_ASSERT(doc[0]["avg"].to<std::string>() == "0.278");
Jesse Beder's avatar
Jesse Beder committed
93
			YAML_ASSERT(doc[1].size() == 3);
94
95
96
			YAML_ASSERT(doc[1]["name"].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc[1]["hr"].to<std::string>() == "63");
			YAML_ASSERT(doc[1]["avg"].to<std::string>() == "0.288");
Jesse Beder's avatar
Jesse Beder committed
97
98
99
			return true;
		}
		
100
		// 2.5
Jesse Beder's avatar
Jesse Beder committed
101
102
103
104
105
106
		TEST SequenceOfSequences()
		{
			std::string input =
				"- [name        , hr, avg  ]\n"
				"- [Mark McGwire, 65, 0.278]\n"
				"- [Sammy Sosa  , 63, 0.288]";
107
108

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
109
110
			YAML_ASSERT(doc.size() == 3);
			YAML_ASSERT(doc[0].size() == 3);
111
112
113
			YAML_ASSERT(doc[0][0].to<std::string>() == "name");
			YAML_ASSERT(doc[0][1].to<std::string>() == "hr");
			YAML_ASSERT(doc[0][2].to<std::string>() == "avg");
Jesse Beder's avatar
Jesse Beder committed
114
			YAML_ASSERT(doc[1].size() == 3);
115
116
117
			YAML_ASSERT(doc[1][0].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc[1][1].to<std::string>() == "65");
			YAML_ASSERT(doc[1][2].to<std::string>() == "0.278");
Jesse Beder's avatar
Jesse Beder committed
118
			YAML_ASSERT(doc[2].size() == 3);
119
120
121
			YAML_ASSERT(doc[2][0].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc[2][1].to<std::string>() == "63");
			YAML_ASSERT(doc[2][2].to<std::string>() == "0.288");
Jesse Beder's avatar
Jesse Beder committed
122
123
124
			return true;
		}
		
125
		// 2.6
Jesse Beder's avatar
Jesse Beder committed
126
127
128
129
130
131
132
133
		TEST MappingOfMappings()
		{
			std::string input =
				"Mark McGwire: {hr: 65, avg: 0.278}\n"
				"Sammy Sosa: {\n"
				"    hr: 63,\n"
				"    avg: 0.288\n"
				"  }";
134
135

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
136
137
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["Mark McGwire"].size() == 2);
138
139
			YAML_ASSERT(doc["Mark McGwire"]["hr"].to<std::string>() == "65");
			YAML_ASSERT(doc["Mark McGwire"]["avg"].to<std::string>() == "0.278");
Jesse Beder's avatar
Jesse Beder committed
140
			YAML_ASSERT(doc["Sammy Sosa"].size() == 2);
141
142
			YAML_ASSERT(doc["Sammy Sosa"]["hr"].to<std::string>() == "63");
			YAML_ASSERT(doc["Sammy Sosa"]["avg"].to<std::string>() == "0.288");
Jesse Beder's avatar
Jesse Beder committed
143
144
145
			return true;
		}
		
146
		// 2.7
Jesse Beder's avatar
Jesse Beder committed
147
148
149
150
151
152
153
154
155
156
157
158
159
		TEST TwoDocumentsInAStream()
		{
			std::string input =
				"# Ranking of 1998 home runs\n"
				"---\n"
				"- Mark McGwire\n"
				"- Sammy Sosa\n"
				"- Ken Griffey\n"
				"\n"
				"# Team ranking\n"
				"---\n"
				"- Chicago Cubs\n"
				"- St Louis Cardinals";
160
161

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
162
			YAML_ASSERT(doc.size() == 3);
163
164
165
			YAML_ASSERT(doc[0].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc[1].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc[2].to<std::string>() == "Ken Griffey");
166
167

			PARSE_NEXT(doc);
Jesse Beder's avatar
Jesse Beder committed
168
			YAML_ASSERT(doc.size() == 2);
169
170
			YAML_ASSERT(doc[0].to<std::string>() == "Chicago Cubs");
			YAML_ASSERT(doc[1].to<std::string>() == "St Louis Cardinals");
Jesse Beder's avatar
Jesse Beder committed
171
172
173
			return true;
		}
		
174
		// 2.8
Jesse Beder's avatar
Jesse Beder committed
175
176
177
178
179
180
181
182
183
184
185
186
187
		TEST PlayByPlayFeed()
		{
			std::string input =
				"---\n"
				"time: 20:03:20\n"
				"player: Sammy Sosa\n"
				"action: strike (miss)\n"
				"...\n"
				"---\n"
				"time: 20:03:47\n"
				"player: Sammy Sosa\n"
				"action: grand slam\n"
				"...";
188
189

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
190
			YAML_ASSERT(doc.size() == 3);
191
192
193
			YAML_ASSERT(doc["time"].to<std::string>() == "20:03:20");
			YAML_ASSERT(doc["player"].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc["action"].to<std::string>() == "strike (miss)");
194
195

			PARSE_NEXT(doc);
Jesse Beder's avatar
Jesse Beder committed
196
			YAML_ASSERT(doc.size() == 3);
197
198
199
			YAML_ASSERT(doc["time"].to<std::string>() == "20:03:47");
			YAML_ASSERT(doc["player"].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc["action"].to<std::string>() == "grand slam");
Jesse Beder's avatar
Jesse Beder committed
200
201
202
			return true;
		}
		
203
		// 2.9
Jesse Beder's avatar
Jesse Beder committed
204
205
206
207
208
209
210
211
212
213
214
		TEST SingleDocumentWithTwoComments()
		{
			std::string input =
				"---\n"
				"hr: # 1998 hr ranking\n"
				"  - Mark McGwire\n"
				"  - Sammy Sosa\n"
				"rbi:\n"
				"  # 1998 rbi ranking\n"
				"  - Sammy Sosa\n"
				"  - Ken Griffey";
215
216

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
217
218
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["hr"].size() == 2);
219
220
			YAML_ASSERT(doc["hr"][0].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc["hr"][1].to<std::string>() == "Sammy Sosa");
Jesse Beder's avatar
Jesse Beder committed
221
			YAML_ASSERT(doc["rbi"].size() == 2);
222
223
			YAML_ASSERT(doc["rbi"][0].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc["rbi"][1].to<std::string>() == "Ken Griffey");
Jesse Beder's avatar
Jesse Beder committed
224
225
226
			return true;
		}
		
227
		// 2.10
Jesse Beder's avatar
Jesse Beder committed
228
229
230
231
232
233
234
235
236
237
238
		TEST SimpleAnchor()
		{
			std::string input =
				"---\n"
				"hr:\n"
				"  - Mark McGwire\n"
				"  # Following node labeled SS\n"
				"  - &SS Sammy Sosa\n"
				"rbi:\n"
				"  - *SS # Subsequent occurrence\n"
				"  - Ken Griffey";
239
240

			PARSE(doc, input);
Jesse Beder's avatar
Jesse Beder committed
241
242
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["hr"].size() == 2);
243
244
			YAML_ASSERT(doc["hr"][0].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc["hr"][1].to<std::string>() == "Sammy Sosa");
Jesse Beder's avatar
Jesse Beder committed
245
			YAML_ASSERT(doc["rbi"].size() == 2);
246
247
			YAML_ASSERT(doc["rbi"][0].to<std::string>() == "Sammy Sosa");
			YAML_ASSERT(doc["rbi"][1].to<std::string>() == "Ken Griffey");
Jesse Beder's avatar
Jesse Beder committed
248
			return true;
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
		}
		
		struct Pair {
			Pair() {}
			Pair(const std::string& f, const std::string& s): first(f), second(s) {}
			std::string first, second;
		};
		
		bool operator == (const Pair& p, const Pair& q) {
			return p.first == q.first && p.second == q.second;
		}
		
		void operator >> (const YAML::Node& node, Pair& p) {
			node[0] >> p.first;
			node[1] >> p.second;
		}
		
266
		// 2.11
267
268
269
270
271
272
273
274
275
276
277
278
279
		TEST MappingBetweenSequences()
		{
			std::string input =
				"? - Detroit Tigers\n"
				"  - Chicago cubs\n"
				":\n"
				"  - 2001-07-23\n"
				"\n"
				"? [ New York Yankees,\n"
				"    Atlanta Braves ]\n"
				": [ 2001-07-02, 2001-08-12,\n"
				"    2001-08-14 ]";

280
			PARSE(doc, input);
281
			YAML_ASSERT(doc.size() == 2);
282
			YAML_ASSERT(doc[Pair("Detroit Tigers", "Chicago cubs")].size() == 1);
283
			YAML_ASSERT(doc[Pair("Detroit Tigers", "Chicago cubs")][0].to<std::string>() == "2001-07-23");
284
			YAML_ASSERT(doc[Pair("New York Yankees", "Atlanta Braves")].size() == 3);
285
286
287
			YAML_ASSERT(doc[Pair("New York Yankees", "Atlanta Braves")][0].to<std::string>() == "2001-07-02");
			YAML_ASSERT(doc[Pair("New York Yankees", "Atlanta Braves")][1].to<std::string>() == "2001-08-12");
			YAML_ASSERT(doc[Pair("New York Yankees", "Atlanta Braves")][2].to<std::string>() == "2001-08-14");
288
289
			return true;
		}
290
		
291
		// 2.12
292
293
294
295
296
297
298
299
300
301
302
		TEST CompactNestedMapping()
		{
			std::string input =
				"---\n"
				"# Products purchased\n"
				"- item    : Super Hoop\n"
				"  quantity: 1\n"
				"- item    : Basketball\n"
				"  quantity: 4\n"
				"- item    : Big Shoes\n"
				"  quantity: 1";
303
304

			PARSE(doc, input);
305
306
			YAML_ASSERT(doc.size() == 3);
			YAML_ASSERT(doc[0].size() == 2);
307
308
			YAML_ASSERT(doc[0]["item"].to<std::string>() == "Super Hoop");
			YAML_ASSERT(doc[0]["quantity"].to<int>() == 1);
309
			YAML_ASSERT(doc[1].size() == 2);
310
311
			YAML_ASSERT(doc[1]["item"].to<std::string>() == "Basketball");
			YAML_ASSERT(doc[1]["quantity"].to<int>() == 4);
312
			YAML_ASSERT(doc[2].size() == 2);
313
314
			YAML_ASSERT(doc[2]["item"].to<std::string>() == "Big Shoes");
			YAML_ASSERT(doc[2]["quantity"].to<int>() == 1);
315
316
317
			return true;
		}
		
318
		// 2.13
319
320
321
322
323
324
325
		TEST InLiteralsNewlinesArePreserved()
		{
			std::string input =
				"# ASCII Art\n"
				"--- |\n"
				"  \\//||\\/||\n"
				"  // ||  ||__";
326
327

			PARSE(doc, input);
328
			YAML_ASSERT(doc.to<std::string>() ==
329
330
331
332
						"\\//||\\/||\n"
						"// ||  ||__");
			return true;
		}
333
334
335
336
337
338
339
340
341
		
		// 2.14
		TEST InFoldedScalarsNewlinesBecomeSpaces()
		{
			std::string input =
				"--- >\n"
				"  Mark McGwire's\n"
				"  year was crippled\n"
				"  by a knee injury.";
342
343

			PARSE(doc, input);
344
			YAML_ASSERT(doc.to<std::string>() == "Mark McGwire's year was crippled by a knee injury.");
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
			return true;
		}
		
		// 2.15
		TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines()
		{
			std::string input =
				">\n"
				" Sammy Sosa completed another\n"
				" fine season with great stats.\n"
				" \n"
				"   63 Home Runs\n"
				"   0.288 Batting Average\n"
				" \n"
				" What a year!";
360
361

			PARSE(doc, input);
362
			YAML_ASSERT(doc.to<std::string>() ==
Jesse Beder's avatar
Jesse Beder committed
363
						"Sammy Sosa completed another fine season with great stats.\n\n"
364
						"  63 Home Runs\n"
Jesse Beder's avatar
Jesse Beder committed
365
						"  0.288 Batting Average\n\n"
366
367
368
369
370
371
372
373
374
375
376
377
378
379
						"What a year!");
			return true;
		}
		
		// 2.16
		TEST IndentationDeterminesScope()
		{
			std::string input =
				"name: Mark McGwire\n"
				"accomplishment: >\n"
				"  Mark set a major league\n"
				"  home run record in 1998.\n"
				"stats: |\n"
				"  65 Home Runs\n"
380
				"  0.278 Batting Average\n";
381
382

			PARSE(doc, input);
383
			YAML_ASSERT(doc.size() == 3);
384
385
386
			YAML_ASSERT(doc["name"].to<std::string>() == "Mark McGwire");
			YAML_ASSERT(doc["accomplishment"].to<std::string>() == "Mark set a major league home run record in 1998.\n");
			YAML_ASSERT(doc["stats"].to<std::string>() == "65 Home Runs\n0.278 Batting Average\n");
387
388
389
390
391
392
393
394
395
396
397
398
399
400
			return true;
		}
		
		// 2.17
		TEST QuotedScalars()
		{
			std::string input =
				"unicode: \"Sosa did fine.\\u263A\"\n"
				"control: \"\\b1998\\t1999\\t2000\\n\"\n"
				"hex esc: \"\\x0d\\x0a is \\r\\n\"\n"
				"\n"
				"single: '\"Howdy!\" he cried.'\n"
				"quoted: ' # Not a ''comment''.'\n"
				"tie-fighter: '|\\-*-/|'";
401
402

			PARSE(doc, input);
403
			YAML_ASSERT(doc.size() == 6);
404
405
406
407
408
409
			YAML_ASSERT(doc["unicode"].to<std::string>() == "Sosa did fine.\xe2\x98\xba");
			YAML_ASSERT(doc["control"].to<std::string>() == "\b1998\t1999\t2000\n");
			YAML_ASSERT(doc["hex esc"].to<std::string>() == "\x0d\x0a is \r\n");
			YAML_ASSERT(doc["single"].to<std::string>() == "\"Howdy!\" he cried.");
			YAML_ASSERT(doc["quoted"].to<std::string>() == " # Not a 'comment'.");
			YAML_ASSERT(doc["tie-fighter"].to<std::string>() == "|\\-*-/|");
410
411
412
413
414
415
416
417
418
419
420
421
422
			return true;
		}
		
		// 2.18
		TEST MultiLineFlowScalars()
		{
			std::string input =
				"plain:\n"
				"  This unquoted scalar\n"
				"  spans many lines.\n"
				"\n"
				"quoted: \"So does this\n"
				"  quoted scalar.\\n\"";
423
424

			PARSE(doc, input);
425
			YAML_ASSERT(doc.size() == 2);
426
427
			YAML_ASSERT(doc["plain"].to<std::string>() == "This unquoted scalar spans many lines.");
			YAML_ASSERT(doc["quoted"].to<std::string>() == "So does this quoted scalar.\n");
428
429
430
			return true;
		}
		
Jesse Beder's avatar
Jesse Beder committed
431
		// TODO: 2.19 - 2.22 schema tags
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
		
		// 2.23
		TEST VariousExplicitTags()
		{
			std::string input =
				"---\n"
				"not-date: !!str 2002-04-28\n"
				"\n"
				"picture: !!binary |\n"
				" R0lGODlhDAAMAIQAAP//9/X\n"
				" 17unp5WZmZgAAAOfn515eXv\n"
				" Pz7Y6OjuDg4J+fn5OTk6enp\n"
				" 56enmleECcgggoBADs=\n"
				"\n"
				"application specific tag: !something |\n"
				" The semantics of the tag\n"
				" above may be different for\n"
				" different documents.";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
453
			YAML_ASSERT(doc["not-date"].Tag() == "tag:yaml.org,2002:str");
454
			YAML_ASSERT(doc["not-date"].to<std::string>() == "2002-04-28");
455
			YAML_ASSERT(doc["picture"].Tag() == "tag:yaml.org,2002:binary");
456
			YAML_ASSERT(doc["picture"].to<std::string>() ==
457
458
459
460
461
				"R0lGODlhDAAMAIQAAP//9/X\n"
				"17unp5WZmZgAAAOfn515eXv\n"
				"Pz7Y6OjuDg4J+fn5OTk6enp\n"
				"56enmleECcgggoBADs=\n"
			);
462
			YAML_ASSERT(doc["application specific tag"].Tag() == "!something");
463
			YAML_ASSERT(doc["application specific tag"].to<std::string>() ==
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
				"The semantics of the tag\n"
				"above may be different for\n"
				"different documents."
			);
			return true;
		}
		
		// 2.24
		TEST GlobalTags()
		{
			std::string input =
				"%TAG ! tag:clarkevans.com,2002:\n"
				"--- !shape\n"
				"  # Use the ! handle for presenting\n"
				"  # tag:clarkevans.com,2002:circle\n"
				"- !circle\n"
				"  center: &ORIGIN {x: 73, y: 129}\n"
				"  radius: 7\n"
				"- !line\n"
				"  start: *ORIGIN\n"
				"  finish: { x: 89, y: 102 }\n"
				"- !label\n"
				"  start: *ORIGIN\n"
				"  color: 0xFFEEBB\n"
				"  text: Pretty vector drawing.";
			
			PARSE(doc, input);
491
			YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:shape");
492
			YAML_ASSERT(doc.size() == 3);
493
			YAML_ASSERT(doc[0].Tag() == "tag:clarkevans.com,2002:circle");
494
495
			YAML_ASSERT(doc[0].size() == 2);
			YAML_ASSERT(doc[0]["center"].size() == 2);
496
497
498
			YAML_ASSERT(doc[0]["center"]["x"].to<int>() == 73);
			YAML_ASSERT(doc[0]["center"]["y"].to<int>() == 129);
			YAML_ASSERT(doc[0]["radius"].to<int>() == 7);
499
			YAML_ASSERT(doc[1].Tag() == "tag:clarkevans.com,2002:line");
500
501
			YAML_ASSERT(doc[1].size() == 2);
			YAML_ASSERT(doc[1]["start"].size() == 2);
502
503
			YAML_ASSERT(doc[1]["start"]["x"].to<int>() == 73);
			YAML_ASSERT(doc[1]["start"]["y"].to<int>() == 129);
504
			YAML_ASSERT(doc[1]["finish"].size() == 2);
505
506
			YAML_ASSERT(doc[1]["finish"]["x"].to<int>() == 89);
			YAML_ASSERT(doc[1]["finish"]["y"].to<int>() == 102);
507
			YAML_ASSERT(doc[2].Tag() == "tag:clarkevans.com,2002:label");
508
509
			YAML_ASSERT(doc[2].size() == 3);
			YAML_ASSERT(doc[2]["start"].size() == 2);
510
511
512
513
			YAML_ASSERT(doc[2]["start"]["x"].to<int>() == 73);
			YAML_ASSERT(doc[2]["start"]["y"].to<int>() == 129);
			YAML_ASSERT(doc[2]["color"].to<std::string>() == "0xFFEEBB");
			YAML_ASSERT(doc[2]["text"].to<std::string>() == "Pretty vector drawing.");
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
			return true;
		}
		
		// 2.25
		TEST UnorderedSets()
		{
			std::string input =
				"# Sets are represented as a\n"
				"# Mapping where each key is\n"
				"# associated with a null value\n"
				"--- !!set\n"
				"? Mark McGwire\n"
				"? Sammy Sosa\n"
				"? Ken Griffey";
			
			PARSE(doc, input);
530
			YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:set");
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
			YAML_ASSERT(doc.size() == 3);
			YAML_ASSERT(IsNull(doc["Mark McGwire"]));
			YAML_ASSERT(IsNull(doc["Sammy Sosa"]));
			YAML_ASSERT(IsNull(doc["Ken Griffey"]));
			return true;
		}
		
		// 2.26
		TEST OrderedMappings()
		{
			std::string input =
				"# Ordered maps are represented as\n"
				"# A sequence of mappings, with\n"
				"# each mapping having one key\n"
				"--- !!omap\n"
				"- Mark McGwire: 65\n"
				"- Sammy Sosa: 63\n"
				"- Ken Griffey: 58";
			
			PARSE(doc, input);
551
			YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:omap");
552
553
			YAML_ASSERT(doc.size() == 3);
			YAML_ASSERT(doc[0].size() == 1);
554
			YAML_ASSERT(doc[0]["Mark McGwire"].to<int>() == 65);
555
			YAML_ASSERT(doc[1].size() == 1);
556
			YAML_ASSERT(doc[1]["Sammy Sosa"].to<int>() == 63);
557
			YAML_ASSERT(doc[2].size() == 1);
558
			YAML_ASSERT(doc[2]["Ken Griffey"].to<int>() == 58);
559
560
			return true;
		}
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
		
		// 2.27
		TEST Invoice()
		{
			std::string input =
				"--- !<tag:clarkevans.com,2002:invoice>\n"
				"invoice: 34843\n"
				"date   : 2001-01-23\n"
				"bill-to: &id001\n"
				"    given  : Chris\n"
				"    family : Dumars\n"
				"    address:\n"
				"        lines: |\n"
				"            458 Walkman Dr.\n"
				"            Suite #292\n"
				"        city    : Royal Oak\n"
				"        state   : MI\n"
				"        postal  : 48046\n"
				"ship-to: *id001\n"
				"product:\n"
				"    - sku         : BL394D\n"
				"      quantity    : 4\n"
				"      description : Basketball\n"
				"      price       : 450.00\n"
				"    - sku         : BL4438H\n"
				"      quantity    : 1\n"
				"      description : Super Hoop\n"
				"      price       : 2392.00\n"
				"tax  : 251.42\n"
				"total: 4443.52\n"
				"comments:\n"
				"    Late afternoon is best.\n"
				"    Backup contact is Nancy\n"
				"    Billsmer @ 338-4338.";
595
596

			PARSE(doc, input);
597
			YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:invoice");
598
			YAML_ASSERT(doc.size() == 8);
599
600
			YAML_ASSERT(doc["invoice"].to<int>() == 34843);
			YAML_ASSERT(doc["date"].to<std::string>() == "2001-01-23");
601
			YAML_ASSERT(doc["bill-to"].size() == 3);
602
603
			YAML_ASSERT(doc["bill-to"]["given"].to<std::string>() == "Chris");
			YAML_ASSERT(doc["bill-to"]["family"].to<std::string>() == "Dumars");
604
			YAML_ASSERT(doc["bill-to"]["address"].size() == 4);
605
606
607
608
			YAML_ASSERT(doc["bill-to"]["address"]["lines"].to<std::string>() == "458 Walkman Dr.\nSuite #292\n");
			YAML_ASSERT(doc["bill-to"]["address"]["city"].to<std::string>() == "Royal Oak");
			YAML_ASSERT(doc["bill-to"]["address"]["state"].to<std::string>() == "MI");
			YAML_ASSERT(doc["bill-to"]["address"]["postal"].to<std::string>() == "48046");
609
			YAML_ASSERT(doc["ship-to"].size() == 3);
610
611
			YAML_ASSERT(doc["ship-to"]["given"].to<std::string>() == "Chris");
			YAML_ASSERT(doc["ship-to"]["family"].to<std::string>() == "Dumars");
612
			YAML_ASSERT(doc["ship-to"]["address"].size() == 4);
613
614
615
616
			YAML_ASSERT(doc["ship-to"]["address"]["lines"].to<std::string>() == "458 Walkman Dr.\nSuite #292\n");
			YAML_ASSERT(doc["ship-to"]["address"]["city"].to<std::string>() == "Royal Oak");
			YAML_ASSERT(doc["ship-to"]["address"]["state"].to<std::string>() == "MI");
			YAML_ASSERT(doc["ship-to"]["address"]["postal"].to<std::string>() == "48046");
617
618
			YAML_ASSERT(doc["product"].size() == 2);
			YAML_ASSERT(doc["product"][0].size() == 4);
619
620
621
622
			YAML_ASSERT(doc["product"][0]["sku"].to<std::string>() == "BL394D");
			YAML_ASSERT(doc["product"][0]["quantity"].to<int>() == 4);
			YAML_ASSERT(doc["product"][0]["description"].to<std::string>() == "Basketball");
			YAML_ASSERT(doc["product"][0]["price"].to<std::string>() == "450.00");
623
			YAML_ASSERT(doc["product"][1].size() == 4);
624
625
626
627
628
629
630
			YAML_ASSERT(doc["product"][1]["sku"].to<std::string>() == "BL4438H");
			YAML_ASSERT(doc["product"][1]["quantity"].to<int>() == 1);
			YAML_ASSERT(doc["product"][1]["description"].to<std::string>() == "Super Hoop");
			YAML_ASSERT(doc["product"][1]["price"].to<std::string>() == "2392.00");
			YAML_ASSERT(doc["tax"].to<std::string>() == "251.42");
			YAML_ASSERT(doc["total"].to<std::string>() == "4443.52");
			YAML_ASSERT(doc["comments"].to<std::string>() == "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.");
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
			return true;
		}
		
		// 2.28
		TEST LogFile()
		{
			std::string input =
				"---\n"
				"Time: 2001-11-23 15:01:42 -5\n"
				"User: ed\n"
				"Warning:\n"
				"  This is an error message\n"
				"  for the log file\n"
				"---\n"
				"Time: 2001-11-23 15:02:31 -5\n"
				"User: ed\n"
				"Warning:\n"
				"  A slightly different error\n"
				"  message.\n"
				"---\n"
				"Date: 2001-11-23 15:03:17 -5\n"
				"User: ed\n"
				"Fatal:\n"
				"  Unknown variable \"bar\"\n"
				"Stack:\n"
				"  - file: TopClass.py\n"
				"    line: 23\n"
				"    code: |\n"
				"      x = MoreObject(\"345\\n\")\n"
				"  - file: MoreClass.py\n"
				"    line: 58\n"
				"    code: |-\n"
				"      foo = bar";
664
665

			PARSE(doc, input);
666
			YAML_ASSERT(doc.size() == 3);
667
668
669
			YAML_ASSERT(doc["Time"].to<std::string>() == "2001-11-23 15:01:42 -5");
			YAML_ASSERT(doc["User"].to<std::string>() == "ed");
			YAML_ASSERT(doc["Warning"].to<std::string>() == "This is an error message for the log file");
670
671

			PARSE_NEXT(doc);
672
			YAML_ASSERT(doc.size() == 3);
673
674
675
			YAML_ASSERT(doc["Time"].to<std::string>() == "2001-11-23 15:02:31 -5");
			YAML_ASSERT(doc["User"].to<std::string>() == "ed");
			YAML_ASSERT(doc["Warning"].to<std::string>() == "A slightly different error message.");
676
677

			PARSE_NEXT(doc);
678
			YAML_ASSERT(doc.size() == 4);
679
680
681
			YAML_ASSERT(doc["Date"].to<std::string>() == "2001-11-23 15:03:17 -5");
			YAML_ASSERT(doc["User"].to<std::string>() == "ed");
			YAML_ASSERT(doc["Fatal"].to<std::string>() == "Unknown variable \"bar\"");
682
683
			YAML_ASSERT(doc["Stack"].size() == 2);
			YAML_ASSERT(doc["Stack"][0].size() == 3);
684
685
686
			YAML_ASSERT(doc["Stack"][0]["file"].to<std::string>() == "TopClass.py");
			YAML_ASSERT(doc["Stack"][0]["line"].to<std::string>() == "23");
			YAML_ASSERT(doc["Stack"][0]["code"].to<std::string>() == "x = MoreObject(\"345\\n\")\n");
687
			YAML_ASSERT(doc["Stack"][1].size() == 3);
688
689
690
			YAML_ASSERT(doc["Stack"][1]["file"].to<std::string>() == "MoreClass.py");
			YAML_ASSERT(doc["Stack"][1]["line"].to<std::string>() == "58");
			YAML_ASSERT(doc["Stack"][1]["code"].to<std::string>() == "foo = bar");
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
			return true;
		}
		
		// TODO: 5.1 - 5.2 BOM
		
		// 5.3
		TEST BlockStructureIndicators()
		{
			std::string input =
				"sequence:\n"
				"- one\n"
				"- two\n"
				"mapping:\n"
				"  ? sky\n"
				"  : blue\n"
				"  sea : green";
707
708

			PARSE(doc, input);
709
710
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["sequence"].size() == 2);
711
712
			YAML_ASSERT(doc["sequence"][0].to<std::string>() == "one");
			YAML_ASSERT(doc["sequence"][1].to<std::string>() == "two");
713
			YAML_ASSERT(doc["mapping"].size() == 2);
714
715
			YAML_ASSERT(doc["mapping"]["sky"].to<std::string>() == "blue");
			YAML_ASSERT(doc["mapping"]["sea"].to<std::string>() == "green");
716
717
718
719
720
721
722
723
724
			return true;
		}
		
		// 5.4
		TEST FlowStructureIndicators()
		{
			std::string input =
				"sequence: [ one, two, ]\n"
				"mapping: { sky: blue, sea: green }";
725
726

			PARSE(doc, input);
727
728
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["sequence"].size() == 2);
729
730
			YAML_ASSERT(doc["sequence"][0].to<std::string>() == "one");
			YAML_ASSERT(doc["sequence"][1].to<std::string>() == "two");
731
			YAML_ASSERT(doc["mapping"].size() == 2);
732
733
			YAML_ASSERT(doc["mapping"]["sky"].to<std::string>() == "blue");
			YAML_ASSERT(doc["mapping"]["sea"].to<std::string>() == "green");
734
735
736
			return true;
		}
		
Jesse Beder's avatar
Jesse Beder committed
737
738
739
740
741
742
743
744
745
746
		// 5.5
		TEST CommentIndicator()
		{
			std::string input =
				"# Comment only.";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 0);
			return true;
		}
747
748
749
750
751
752
753
		
		// 5.6
		TEST NodePropertyIndicators()
		{
			std::string input =
				"anchored: !local &anchor value\n"
				"alias: *anchor";
754
755

			PARSE(doc, input);
756
			YAML_ASSERT(doc.size() == 2);
757
758
			YAML_ASSERT(doc["anchored"].to<std::string>() == "value"); // TODO: assert tag
			YAML_ASSERT(doc["alias"].to<std::string>() == "value");
759
760
761
762
763
764
765
766
767
768
769
770
771
			return true;
		}
		
		// 5.7
		TEST BlockScalarIndicators()
		{
			std::string input =
				"literal: |\n"
				"  some\n"
				"  text\n"
				"folded: >\n"
				"  some\n"
				"  text\n";
772
773

			PARSE(doc, input);
774
			YAML_ASSERT(doc.size() == 2);
775
776
			YAML_ASSERT(doc["literal"].to<std::string>() == "some\ntext\n");
			YAML_ASSERT(doc["folded"].to<std::string>() == "some text\n");
777
778
779
780
781
782
783
784
785
			return true;
		}
		
		// 5.8
		TEST QuotedScalarIndicators()
		{
			std::string input =
				"single: 'text'\n"
				"double: \"text\"";
786
787

			PARSE(doc, input);
788
			YAML_ASSERT(doc.size() == 2);
789
790
			YAML_ASSERT(doc["single"].to<std::string>() == "text");
			YAML_ASSERT(doc["double"].to<std::string>() == "text");
791
792
793
794
795
796
797
798
799
800
801
802
803
			return true;
		}
		
		// TODO: 5.9 directive
		// TODO: 5.10 reserved indicator
		
		// 5.11
		TEST LineBreakCharacters()
		{
			std::string input =
				"|\n"
				"  Line break (no glyph)\n"
				"  Line break (glyphed)\n";
804
805

			PARSE(doc, input);
806
			YAML_ASSERT(doc.to<std::string>() == "Line break (no glyph)\nLine break (glyphed)\n");
807
808
809
810
811
812
813
814
815
816
817
818
819
			return true;
		}
		
		// 5.12
		TEST TabsAndSpaces()
		{
			std::string input =
				"# Tabs and spaces\n"
				"quoted: \"Quoted\t\"\n"
				"block:	|\n"
				"  void main() {\n"
				"  \tprintf(\"Hello, world!\\n\");\n"
				"  }";
820
821

			PARSE(doc, input);
822
			YAML_ASSERT(doc.size() == 2);
823
824
			YAML_ASSERT(doc["quoted"].to<std::string>() == "Quoted\t");
			YAML_ASSERT(doc["block"].to<std::string>() ==
825
826
827
828
829
						"void main() {\n"
						"\tprintf(\"Hello, world!\\n\");\n"
						"}");
			return true;
		}
830
831
832
833
834
835
836
837
838
839
		
		// 5.13
		TEST EscapedCharacters()
		{
			std::string input =
				"\"Fun with \\\\\n"
				"\\\" \\a \\b \\e \\f \\\n"
				"\\n \\r \\t \\v \\0 \\\n"
				"\\  \\_ \\N \\L \\P \\\n"
				"\\x41 \\u0041 \\U00000041\"";
840
841

			PARSE(doc, input);
842
			YAML_ASSERT(doc.to<std::string>() == "Fun with \x5C \x22 \x07 \x08 \x1B \x0C \x0A \x0D \x09 \x0B " + std::string("\x00", 1) + " \x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9 A A A");
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
			return true;
		}
		
		// 5.14
		TEST InvalidEscapedCharacters()
		{
			std::string input =
				"Bad escapes:\n"
				"  \"\\c\n"
				"  \\xq-\"";
			
			std::stringstream stream(input);
			try {
				YAML::Parser parser(stream);
				YAML::Node doc;
				parser.GetNextDocument(doc);
			} catch(const YAML::ParserException& e) {
860
				YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::INVALID_ESCAPE) + "c");
861
862
863
864
865
				return true;
			}
			
			return false;
		}
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
		
		// 6.1
		TEST IndentationSpaces()
		{
			std::string input =
				"  # Leading comment line spaces are\n"
				"   # neither content nor indentation.\n"
				"    \n"
				"Not indented:\n"
				" By one space: |\n"
				"    By four\n"
				"      spaces\n"
				" Flow style: [    # Leading spaces\n"
				"   By two,        # in flow style\n"
				"  Also by two,    # are neither\n"
				"  \tStill by two   # content nor\n"
				"    ]             # indentation.";
883
884

			PARSE(doc, input);
885
886
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["Not indented"].size() == 2);
887
			YAML_ASSERT(doc["Not indented"]["By one space"].to<std::string>() == "By four\n  spaces\n");
888
			YAML_ASSERT(doc["Not indented"]["Flow style"].size() == 3);
889
890
891
			YAML_ASSERT(doc["Not indented"]["Flow style"][0].to<std::string>() == "By two");
			YAML_ASSERT(doc["Not indented"]["Flow style"][1].to<std::string>() == "Also by two");
			YAML_ASSERT(doc["Not indented"]["Flow style"][2].to<std::string>() == "Still by two");
892
893
894
895
896
897
898
899
900
901
902
			return true;
		}
		
		// 6.2
		TEST IndentationIndicators()
		{
			std::string input =
				"? a\n"
				": -\tb\n"
				"  -  -\tc\n"
				"     - d";
903
904

			PARSE(doc, input);
905
906
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["a"].size() == 2);
907
			YAML_ASSERT(doc["a"][0].to<std::string>() == "b");
908
			YAML_ASSERT(doc["a"][1].size() == 2);
909
910
			YAML_ASSERT(doc["a"][1][0].to<std::string>() == "c");
			YAML_ASSERT(doc["a"][1][1].to<std::string>() == "d");
911
912
913
914
915
916
917
918
919
920
			return true;
		}
		
		// 6.3
		TEST SeparationSpaces()
		{
			std::string input =
				"- foo:\t bar\n"
				"- - baz\n"
				"  -\tbaz";
921
922

			PARSE(doc, input);
923
924
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc[0].size() == 1);
925
			YAML_ASSERT(doc[0]["foo"].to<std::string>() == "bar");
926
			YAML_ASSERT(doc[1].size() == 2);
927
928
			YAML_ASSERT(doc[1][0].to<std::string>() == "baz");
			YAML_ASSERT(doc[1][1].to<std::string>() == "baz");
929
930
931
932
933
934
935
936
937
938
939
940
941
942
			return true;
		}
		
		// 6.4
		TEST LinePrefixes()
		{
			std::string input =
				"plain: text\n"
				"  lines\n"
				"quoted: \"text\n"
				"  \tlines\"\n"
				"block: |\n"
				"  text\n"
				"   \tlines\n";
943
944

			PARSE(doc, input);
945
			YAML_ASSERT(doc.size() == 3);
946
947
948
			YAML_ASSERT(doc["plain"].to<std::string>() == "text lines");
			YAML_ASSERT(doc["quoted"].to<std::string>() == "text lines");
			YAML_ASSERT(doc["block"].to<std::string>() == "text\n \tlines\n");
949
950
951
952
953
954
955
956
957
958
959
960
961
962
			return true;
		}
		
		// 6.5
		TEST EmptyLines()
		{
			std::string input =
				"Folding:\n"
				"  \"Empty line\n"
				"   \t\n"
				"  as a line feed\"\n"
				"Chomping: |\n"
				"  Clipped empty lines\n"
				" ";
963
964

			PARSE(doc, input);
965
			YAML_ASSERT(doc.size() == 2);
966
967
			YAML_ASSERT(doc["Folding"].to<std::string>() == "Empty line\nas a line feed");
			YAML_ASSERT(doc["Chomping"].to<std::string>() == "Clipped empty lines\n");
968
969
			return true;
		}
970
971
972
973
974
975
976
977
978
979
980
981
		
		// 6.6
		TEST LineFolding()
		{
			std::string input =
				">-\n"
				"  trimmed\n"
				"  \n"
				" \n"
				"\n"
				"  as\n"
				"  space";
982
983

			PARSE(doc, input);
984
			YAML_ASSERT(doc.to<std::string>() == "trimmed\n\n\nas space");
985
986
987
988
989
990
991
992
993
994
995
996
997
			return true;
		}
		
		// 6.7
		TEST BlockFolding()
		{
			std::string input =
				">\n"
				"  foo \n"
				" \n"
				"  \t bar\n"
				"\n"
				"  baz\n";
998
999

			PARSE(doc, input);
1000
			YAML_ASSERT(doc.to<std::string>() == "foo \n\n\t bar\n\nbaz\n");
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
			return true;
		}
		
		// 6.8
		TEST FlowFolding()
		{
			std::string input =
				"\"\n"
				"  foo \n"
				" \n"
				"  \t bar\n"
				"\n"
				"  baz\n"
				"\"";
1015
1016

			PARSE(doc, input);			
1017
			YAML_ASSERT(doc.to<std::string>() == " foo\nbar\nbaz ");
1018
1019
			return true;
		}
1020
1021
1022
1023
1024
1025
1026
		
		// 6.9
		TEST SeparatedComment()
		{
			std::string input =
				"key:    # Comment\n"
				"  value";
1027
1028

			PARSE(doc, input);
1029
			YAML_ASSERT(doc.size() == 1);
1030
			YAML_ASSERT(doc["key"].to<std::string>() == "value");
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
			return true;
		}
		
		// 6.10
		TEST CommentLines()
		{
			std::string input =
				"  # Comment\n"
				"   \n"
				"\n";
			
Jesse Beder's avatar
Jesse Beder committed
1042
1043
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 0);
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
			return true;
		}
		
		// 6.11
		TEST MultiLineComments()
		{
			std::string input =
				"key:    # Comment\n"
				"        # lines\n"
				"  value\n"
				"\n";
1055
1056

			PARSE(doc, input);
1057
			YAML_ASSERT(doc.size() == 1);
1058
			YAML_ASSERT(doc["key"].to<std::string>() == "value");
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
			return true;
		}

		struct StringMap {
			typedef std::map<std::string, std::string> Map;
			Map _;
		};
		
		bool operator == (const StringMap& m, const StringMap& n) {
			return m._ == n._;
		}
		
		void operator >> (const YAML::Node& node, StringMap& m) {
			m._.clear();
			for(YAML::Iterator it=node.begin();it!=node.end();++it) {
1074
1075
				std::string key = it.first().to<std::string>();
				std::string value = it.second().to<std::string>();
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
				m._[key] = value;
			}
		}

		
		// 6.12
		TEST SeparationSpacesII()
		{
			std::string input =
				"{ first: Sammy, last: Sosa }:\n"
				"# Statistics:\n"
				"  hr:  # Home runs\n"
				"     65\n"
				"  avg: # Average\n"
				"   0.278";
1091
1092

			PARSE(doc, input);
1093
1094
1095
			std::map<std::string, std::string> key;
			key["first"] = "Sammy";
			key["last"] = "Sosa";
1096
1097
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc[key].size() == 2);
1098
1099
			YAML_ASSERT(doc[key]["hr"].to<int>() == 65);
			YAML_ASSERT(doc[key]["avg"].to<std::string>() == "0.278");
1100
1101
1102
			return true;
		}
		
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
		// 6.13
		TEST ReservedDirectives()
		{
			std::string input =
				"%FOO  bar baz # Should be ignored\n"
				"               # with a warning.\n"
				"--- \"foo\"";

			PARSE(doc, input);
			return true;
		}
		
		// 6.14
		TEST YAMLDirective()
		{
			std::string input =
				"%YAML 1.3 # Attempt parsing\n"
				"           # with a warning\n"
				"---\n"
				"\"foo\"";

			PARSE(doc, input);
			return true;
		}
		
		// 6.15
		TEST InvalidRepeatedYAMLDirective()
		{
			std::string input =
				"%YAML 1.2\n"
				"%YAML 1.1\n"
				"foo";

			try {
				PARSE(doc, input);
			} catch(const YAML::ParserException& e) {
				if(e.msg == YAML::ErrorMsg::REPEATED_YAML_DIRECTIVE)
					return true;

				throw;
			}
			
			return "  No exception was thrown";
		}
		
		// 6.16
		TEST TagDirective()
		{
			std::string input =
				"%TAG !yaml! tag:yaml.org,2002:\n"
				"---\n"
				"!yaml!str \"foo\"";
			
			PARSE(doc, input);
1157
			YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:str");
1158
			YAML_ASSERT(doc.to<std::string>() == "foo");
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
			return true;
		}
		
		// 6.17
		TEST InvalidRepeatedTagDirective()
		{
			std::string input =
				"%TAG ! !foo\n"
				"%TAG ! !foo\n"
				"bar";

			try {
				PARSE(doc, input);
			} catch(const YAML::ParserException& e) {
				if(e.msg == YAML::ErrorMsg::REPEATED_TAG_DIRECTIVE)
					return true;
				
				throw;
			}
	
			return "  No exception was thrown";
		}

		// 6.18
		TEST PrimaryTagHandle()
		{
			std::string input =
				"# Private\n"
				"!foo \"bar\"\n"
				"...\n"
				"# Global\n"
				"%TAG ! tag:example.com,2000:app/\n"
				"---\n"
				"!foo \"bar\"";

			PARSE(doc, input);
1195
			YAML_ASSERT(doc.Tag() == "!foo");
1196
			YAML_ASSERT(doc.to<std::string>() == "bar");
1197
1198

			PARSE_NEXT(doc);
1199
			YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo");
1200
			YAML_ASSERT(doc.to<std::string>() == "bar");
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
			return true;
		}
		
		// 6.19
		TEST SecondaryTagHandle()
		{
			std::string input =
				"%TAG !! tag:example.com,2000:app/\n"
				"---\n"
				"!!int 1 - 3 # Interval, not integer";
			
			PARSE(doc, input);
1213
			YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/int");
1214
			YAML_ASSERT(doc.to<std::string>() == "1 - 3");
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
			return true;
		}
		
		// 6.20
		TEST TagHandles()
		{
			std::string input =
				"%TAG !e! tag:example.com,2000:app/\n"
				"---\n"
				"!e!foo \"bar\"";
			
			PARSE(doc, input);
1227
			YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo");
1228
			YAML_ASSERT(doc.to<std::string>() == "bar");
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
			return true;
		}
		
		// 6.21
		TEST LocalTagPrefix()
		{
			std::string input =
				"%TAG !m! !my-\n"
				"--- # Bulb here\n"
				"!m!light fluorescent\n"
				"...\n"
				"%TAG !m! !my-\n"
				"--- # Color here\n"
				"!m!light green";
			
			PARSE(doc, input);
1245
			YAML_ASSERT(doc.Tag() == "!my-light");
1246
			YAML_ASSERT(doc.to<std::string>() == "fluorescent");
1247
1248
			
			PARSE_NEXT(doc);
1249
			YAML_ASSERT(doc.Tag() == "!my-light");
1250
			YAML_ASSERT(doc.to<std::string>() == "green");
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
			return true;
		}
		
		// 6.22
		TEST GlobalTagPrefix()
		{
			std::string input =
				"%TAG !e! tag:example.com,2000:app/\n"
				"---\n"
				"- !e!foo \"bar\"";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
1264
			YAML_ASSERT(doc[0].Tag() == "tag:example.com,2000:app/foo");
1265
			YAML_ASSERT(doc[0].to<std::string>() == "bar");
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
			return true;
		}
		
		// 6.23
		TEST NodeProperties()
		{
			std::string input =
				"!!str &a1 \"foo\":\n"
				"  !!str bar\n"
				"&a2 baz : *a1";

			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
			for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
1280
				if(it.first().to<std::string>() == "foo") {
1281
1282
					YAML_ASSERT(it.first().Tag() == "tag:yaml.org,2002:str");
					YAML_ASSERT(it.second().Tag() == "tag:yaml.org,2002:str");
1283
1284
1285
					YAML_ASSERT(it.second().to<std::string>() == "bar");
				} else if(it.first().to<std::string>() == "baz") {
					YAML_ASSERT(it.second().to<std::string>() == "foo");
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
				} else
					return "  unknown key";
			}
			
			return true;
		}
		
		// 6.24
		TEST VerbatimTags()
		{
			std::string input =
				"!<tag:yaml.org,2002:str> foo :\n"
				"  !<!bar> baz";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
1303
				YAML_ASSERT(it.first().Tag() == "tag:yaml.org,2002:str");
1304
				YAML_ASSERT(it.first().to<std::string>() == "foo");
1305
				YAML_ASSERT(it.second().Tag() == "!bar");
1306
				YAML_ASSERT(it.second().to<std::string>() == "baz");
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
			}
			return true;
		}
		
		// 6.25
		TEST InvalidVerbatimTags()
		{
			std::string input =
				"- !<!> foo\n"
				"- !<$:?> bar\n";

			PARSE(doc, input);
			return "  not implemented yet"; // TODO: check tags (but we probably will say these are valid, I think)
		}
		
		// 6.26
		TEST TagShorthands()
		{
			std::string input =
				"%TAG !e! tag:example.com,2000:app/\n"
				"---\n"
				"- !local foo\n"
				"- !!str bar\n"
				"- !e!tag%21 baz\n";

			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
1334
			YAML_ASSERT(doc[0].Tag() == "!local");
1335
			YAML_ASSERT(doc[0].to<std::string>() == "foo");
1336
			YAML_ASSERT(doc[1].Tag() == "tag:yaml.org,2002:str");
1337
			YAML_ASSERT(doc[1].to<std::string>() == "bar");
1338
			YAML_ASSERT(doc[2].Tag() == "tag:example.com,2000:app/tag%21");
1339
			YAML_ASSERT(doc[2].to<std::string>() == "baz");
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
			return true;
		}
		
		// 6.27
		TEST InvalidTagShorthands()
		{
			std::string input1 =
				"%TAG !e! tag:example,2000:app/\n"
				"---\n"
				"- !e! foo";

			bool threw = false;
			try {
				PARSE(doc, input1);
			} catch(const YAML::ParserException& e) {
				threw = true;
				if(e.msg != YAML::ErrorMsg::TAG_WITH_NO_SUFFIX)
					throw;
			}
			
			if(!threw)
				return "  No exception was thrown for a tag with no suffix";

			std::string input2 =
				"%TAG !e! tag:example,2000:app/\n"
				"---\n"
				"- !h!bar baz";

			PARSE(doc, input2); // TODO: should we reject this one (since !h! is not declared)?
			return "  not implemented yet";
		}
		
		// 6.28
		TEST NonSpecificTags()
		{
			std::string input =
				"# Assuming conventional resolution:\n"
				"- \"12\"\n"
				"- 12\n"
				"- ! 12";

			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
1383
1384
1385
			YAML_ASSERT(doc[0].to<std::string>() == "12"); // TODO: check tags. How?
			YAML_ASSERT(doc[1].to<int>() == 12);
			YAML_ASSERT(doc[2].to<std::string>() == "12");
1386
1387
			return true;
		}
1388
1389
1390
1391
1392
1393
1394

		// 6.29
		TEST NodeAnchors()
		{
			std::string input =
				"First occurrence: &anchor Value\n"
				"Second occurrence: *anchor";
1395
1396

			PARSE(doc, input);
1397
			YAML_ASSERT(doc.size() == 2);
1398
1399
			YAML_ASSERT(doc["First occurrence"].to<std::string>() == "Value");
			YAML_ASSERT(doc["Second occurrence"].to<std::string>() == "Value");
1400
1401
			return true;
		}
1402
1403
1404
1405
1406
1407
1408
1409
1410
		
		// 7.1
		TEST AliasNodes()
		{
			std::string input =
				"First occurrence: &anchor Foo\n"
				"Second occurrence: *anchor\n"
				"Override anchor: &anchor Bar\n"
				"Reuse anchor: *anchor";
1411
1412

			PARSE(doc, input);
1413
			YAML_ASSERT(doc.size() == 4);
1414
1415
1416
1417
			YAML_ASSERT(doc["First occurrence"].to<std::string>() == "Foo");
			YAML_ASSERT(doc["Second occurrence"].to<std::string>() == "Foo");
			YAML_ASSERT(doc["Override anchor"].to<std::string>() == "Bar");
			YAML_ASSERT(doc["Reuse anchor"].to<std::string>() == "Bar");
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
			return true;
		}
		
		// 7.2
		TEST EmptyNodes()
		{
			std::string input =
				"{\n"
				"  foo : !!str,\n"
				"  !!str : bar,\n"
				"}";
1429
1430

			PARSE(doc, input);
1431
			YAML_ASSERT(doc.size() == 2);
1432
			for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
1433
				if(it.first().to<std::string>() == "foo") {
1434
					YAML_ASSERT(it.second().Tag() == "tag:yaml.org,2002:str");
1435
1436
					YAML_ASSERT(it.second().to<std::string>() == "");
				} else if(it.first().to<std::string>() == "") {
1437
					YAML_ASSERT(it.first().Tag() == "tag:yaml.org,2002:str");
1438
					YAML_ASSERT(it.second().to<std::string>() == "bar");
1439
1440
1441
				} else
					return "  unexpected key";
			}
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
			return true;
		}
		
		// 7.3
		TEST CompletelyEmptyNodes()
		{
			std::string input =
				"{\n"
				"  ? foo :,\n"
				"  : bar,\n"
				"}\n";
1453
1454

			PARSE(doc, input);
1455
1456
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(IsNull(doc["foo"]));
1457
			YAML_ASSERT(doc[YAML::Null].to<std::string>() == "bar");
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
			return true;
		}
		
		// 7.4
		TEST DoubleQuotedImplicitKeys()
		{
			std::string input =
				"\"implicit block key\" : [\n"
				"  \"implicit flow key\" : value,\n"
				" ]";
1468
1469
1470
1471
1472

			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["implicit block key"].size() == 1);
			YAML_ASSERT(doc["implicit block key"][0].size() == 1);
1473
			YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].to<std::string>() == "value");
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
			return true;
		}
		
		// 7.5
		TEST DoubleQuotedLineBreaks()
		{
			std::string input =
				"\"folded \n"
				"to a space,\t\n"
				" \n"
				"to a line feed, or \t\\\n"
				" \\ \tnon-content\"";

			PARSE(doc, input);
1488
			YAML_ASSERT(doc.to<std::string>() == "folded to a space,\nto a line feed, or \t \tnon-content");
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
			return true;
		}
		
		// 7.6
		TEST DoubleQuotedLines()
		{
			std::string input =
				"\" 1st non-empty\n"
				"\n"
				" 2nd non-empty \n"
				"\t3rd non-empty \"";

			PARSE(doc, input);
1502
			YAML_ASSERT(doc.to<std::string>() == " 1st non-empty\n2nd non-empty 3rd non-empty ");
1503
1504
1505
1506
1507
1508
1509
1510
1511
			return true;
		}
		
		// 7.7
		TEST SingleQuotedCharacters()
		{
			std::string input = " 'here''s to \"quotes\"'";

			PARSE(doc, input);
1512
			YAML_ASSERT(doc.to<std::string>() == "here's to \"quotes\"");
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
			return true;
		}
		
		// 7.8
		TEST SingleQuotedImplicitKeys()
		{
			std::string input =
				"'implicit block key' : [\n"
				"  'implicit flow key' : value,\n"
				" ]";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["implicit block key"].size() == 1);
			YAML_ASSERT(doc["implicit block key"][0].size() == 1);
1528
			YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].to<std::string>() == "value");
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
			return true;
		}
		
		// 7.9
		TEST SingleQuotedLines()
		{
			std::string input =
				"' 1st non-empty\n"
				"\n"
				" 2nd non-empty \n"
				"\t3rd non-empty '";
			
			PARSE(doc, input);
1542
			YAML_ASSERT(doc.to<std::string>() == " 1st non-empty\n2nd non-empty 3rd non-empty ");
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
			return true;
		}
		
		// 7.10
		TEST PlainCharacters()
		{
			std::string input =
				"# Outside flow collection:\n"
				"- ::vector\n"
				"- \": - ()\"\n"
				"- Up, up, and away!\n"
				"- -123\n"
				"- http://example.com/foo#bar\n"
				"# Inside flow collection:\n"
				"- [ ::vector,\n"
				"  \": - ()\",\n"
				"  \"Up, up, and away!\",\n"
				"  -123,\n"
				"  http://example.com/foo#bar ]";
1562
			
1563
1564
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 6);
1565
1566
1567
1568
1569
			YAML_ASSERT(doc[0].to<std::string>() == "::vector");
			YAML_ASSERT(doc[1].to<std::string>() == ": - ()");
			YAML_ASSERT(doc[2].to<std::string>() == "Up, up, and away!");
			YAML_ASSERT(doc[3].to<int>() == -123);
			YAML_ASSERT(doc[4].to<std::string>() == "http://example.com/foo#bar");
1570
			YAML_ASSERT(doc[5].size() == 5);
1571
1572
1573
1574
1575
			YAML_ASSERT(doc[5][0].to<std::string>() == "::vector");
			YAML_ASSERT(doc[5][1].to<std::string>() == ": - ()");
			YAML_ASSERT(doc[5][2].to<std::string>() == "Up, up, and away!");
			YAML_ASSERT(doc[5][3].to<int>() == -123);
			YAML_ASSERT(doc[5][4].to<std::string>() == "http://example.com/foo#bar");
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
			return true;
		}
		
		// 7.11
		TEST PlainImplicitKeys()
		{
			std::string input =
				"implicit block key : [\n"
				"  implicit flow key : value,\n"
				" ]";

			PARSE(doc, input);
1588
1589
1590
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["implicit block key"].size() == 1);
			YAML_ASSERT(doc["implicit block key"][0].size() == 1);
1591
			YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].to<std::string>() == "value");
1592
1593
			return true;
		}
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
		
		// 7.12
		TEST PlainLines()
		{
			std::string input =
				"1st non-empty\n"
				"\n"
				" 2nd non-empty \n"
				"\t3rd non-empty";
			
			PARSE(doc, input);
1605
			YAML_ASSERT(doc.to<std::string>() == "1st non-empty\n2nd non-empty 3rd non-empty");
1606
1607
			return true;
		}
Jesse Beder's avatar
Jesse Beder committed
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
		
		// 7.13
		TEST FlowSequence()
		{
			std::string input =
				"- [ one, two, ]\n"
				"- [three ,four]";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc[0].size() == 2);
1619
1620
			YAML_ASSERT(doc[0][0].to<std::string>() == "one");
			YAML_ASSERT(doc[0][1].to<std::string>() == "two");
Jesse Beder's avatar
Jesse Beder committed
1621
			YAML_ASSERT(doc[1].size() == 2);
1622
1623
			YAML_ASSERT(doc[1][0].to<std::string>() == "three");
			YAML_ASSERT(doc[1][1].to<std::string>() == "four");
Jesse Beder's avatar
Jesse Beder committed
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
			return true;
		}
		
		// 7.14
		TEST FlowSequenceEntries()
		{
			std::string input =
				"[\n"
				"\"double\n"
				" quoted\", 'single\n"
				"           quoted',\n"
				"plain\n"
				" text, [ nested ],\n"
				"single: pair,\n"
				"]";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 5);
1642
1643
1644
			YAML_ASSERT(doc[0].to<std::string>() == "double quoted");
			YAML_ASSERT(doc[1].to<std::string>() == "single quoted");
			YAML_ASSERT(doc[2].to<std::string>() == "plain text");
Jesse Beder's avatar
Jesse Beder committed
1645
			YAML_ASSERT(doc[3].size() == 1);
1646
			YAML_ASSERT(doc[3][0].to<std::string>() == "nested");
Jesse Beder's avatar
Jesse Beder committed
1647
			YAML_ASSERT(doc[4].size() == 1);
1648
			YAML_ASSERT(doc[4]["single"].to<std::string>() == "pair");
Jesse Beder's avatar
Jesse Beder committed
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
			return true;
		}
		
		// 7.15
		TEST FlowMappings()
		{
			std::string input =
				"- { one : two , three: four , }\n"
				"- {five: six,seven : eight}";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc[0].size() == 2);
1662
1663
			YAML_ASSERT(doc[0]["one"].to<std::string>() == "two");
			YAML_ASSERT(doc[0]["three"].to<std::string>() == "four");
Jesse Beder's avatar
Jesse Beder committed
1664
			YAML_ASSERT(doc[1].size() == 2);
1665
1666
			YAML_ASSERT(doc[1]["five"].to<std::string>() == "six");
			YAML_ASSERT(doc[1]["seven"].to<std::string>() == "eight");
Jesse Beder's avatar
Jesse Beder committed
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
			return true;
		}
		
		// 7.16
		TEST FlowMappingEntries()
		{
			std::string input =
				"{\n"
				"? explicit: entry,\n"
				"implicit: entry,\n"
				"?\n"
				"}";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
1682
1683
			YAML_ASSERT(doc["explicit"].to<std::string>() == "entry");
			YAML_ASSERT(doc["implicit"].to<std::string>() == "entry");
Jesse Beder's avatar
Jesse Beder committed
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
			YAML_ASSERT(IsNull(doc[YAML::Null]));
			return true;
		}
		
		// 7.17
		TEST FlowMappingSeparateValues()
		{
			std::string input =
				"{\n"
				"unquoted : \"separate\",\n"
				"http://foo.com,\n"
				"omitted value:,\n"
				": omitted key,\n"
				"}";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 4);
1701
			YAML_ASSERT(doc["unquoted"].to<std::string>() == "separate");
Jesse Beder's avatar
Jesse Beder committed
1702
1703
			YAML_ASSERT(IsNull(doc["http://foo.com"]));
			YAML_ASSERT(IsNull(doc["omitted value"]));
1704
			YAML_ASSERT(doc[YAML::Null].to<std::string>() == "omitted key");
Jesse Beder's avatar
Jesse Beder committed
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
			return true;
		}
		
		// 7.18
		TEST FlowMappingAdjacentValues()
		{
			std::string input =
				"{\n"
				"\"adjacent\":value,\n"
				"\"readable\":value,\n"
				"\"empty\":\n"
				"}";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
1720
1721
			YAML_ASSERT(doc["adjacent"].to<std::string>() == "value");
			YAML_ASSERT(doc["readable"].to<std::string>() == "value");
Jesse Beder's avatar
Jesse Beder committed
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
			YAML_ASSERT(IsNull(doc["empty"]));
			return true;
		}
		
		// 7.19
		TEST SinglePairFlowMappings()
		{
			std::string input =
				"[\n"
				"foo: bar\n"
				"]";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc[0].size() == 1);
1737
			YAML_ASSERT(doc[0]["foo"].to<std::string>() == "bar");
Jesse Beder's avatar
Jesse Beder committed
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
			return true;
		}
		
		// 7.20
		TEST SinglePairExplicitEntry()
		{
			std::string input =
				"[\n"
				"? foo\n"
				" bar : baz\n"
				"]";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc[0].size() == 1);
1753
			YAML_ASSERT(doc[0]["foo bar"].to<std::string>() == "baz");
Jesse Beder's avatar
Jesse Beder committed
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
			return true;
		}
		
		// 7.21
		TEST SinglePairImplicitEntries()
		{
			std::string input =
				"- [ YAML : separate ]\n"
				"- [ : empty key entry ]\n"
				"- [ {JSON: like}:adjacent ]";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
			YAML_ASSERT(doc[0].size() == 1);
			YAML_ASSERT(doc[0][0].size() == 1);
1769
			YAML_ASSERT(doc[0][0]["YAML"].to<std::string>() == "separate");
Jesse Beder's avatar
Jesse Beder committed
1770
1771
			YAML_ASSERT(doc[1].size() == 1);
			YAML_ASSERT(doc[1][0].size() == 1);
1772
			YAML_ASSERT(doc[1][0][YAML::Null].to<std::string>() == "empty key entry");
Jesse Beder's avatar
Jesse Beder committed
1773
1774
1775
1776
			YAML_ASSERT(doc[2].size() == 1);
			YAML_ASSERT(doc[2][0].size() == 1);
			StringMap key;
			key._["JSON"] = "like";
1777
			YAML_ASSERT(doc[2][0][key].to<std::string>() == "adjacent");
Jesse Beder's avatar
Jesse Beder committed
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
			return true;
		}
		
		// 7.22
		TEST InvalidImplicitKeys()
		{
			std::string input =
				"[ foo\n"
				" bar: invalid,"; // Note: we don't check (on purpose) the >1K chars for an implicit key
			
			try {
				PARSE(doc, input);
			} catch(const YAML::Exception& e) {
Jesse Beder's avatar
Jesse Beder committed
1791
				if(e.msg == YAML::ErrorMsg::END_OF_SEQ_FLOW)
Jesse Beder's avatar
Jesse Beder committed
1792
1793
1794
1795
1796
1797
					return true;
				
				throw;
			}
			return "  no exception thrown";
		}
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
		
		// 7.23
		TEST FlowContent()
		{
			std::string input =
				"- [ a, b ]\n"
				"- { a: b }\n"
				"- \"a\"\n"
				"- 'b'\n"
				"- c";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 5);
			YAML_ASSERT(doc[0].size() == 2);
1812
1813
			YAML_ASSERT(doc[0][0].to<std::string>() == "a");
			YAML_ASSERT(doc[0][1].to<std::string>() == "b");
1814
			YAML_ASSERT(doc[1].size() == 1);
1815
1816
1817
1818
			YAML_ASSERT(doc[1]["a"].to<std::string>() == "b");
			YAML_ASSERT(doc[2].to<std::string>() == "a");
			YAML_ASSERT(doc[3].to<char>() == 'b');
			YAML_ASSERT(doc[4].to<std::string>() == "c");
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
			return true;
		}
		
		// 7.24
		TEST FlowNodes()
		{
			std::string input =
				"- !!str \"a\"\n"
				"- 'b'\n"
				"- &anchor \"c\"\n"
				"- *anchor\n"
				"- !!str";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 5);
1834
			YAML_ASSERT(doc[0].Tag() == "tag:yaml.org,2002:str");
1835
1836
1837
1838
			YAML_ASSERT(doc[0].to<std::string>() == "a");
			YAML_ASSERT(doc[1].to<char>() == 'b');
			YAML_ASSERT(doc[2].to<std::string>() == "c");
			YAML_ASSERT(doc[3].to<std::string>() == "c");
1839
			YAML_ASSERT(doc[4].Tag() == "tag:yaml.org,2002:str");
1840
			YAML_ASSERT(doc[4].to<std::string>() == "");
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
			return true;
		}
		
		// 8.1
		TEST BlockScalarHeader()
		{
			std::string input =
				"- | # Empty header\n"
				" literal\n"
				"- >1 # Indentation indicator\n"
				"  folded\n"
				"- |+ # Chomping indicator\n"
				" keep\n"
				"\n"
				"- >1- # Both indicators\n"
				"  strip\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 4);
1860
1861
1862
1863
			YAML_ASSERT(doc[0].to<std::string>() == "literal\n");
			YAML_ASSERT(doc[1].to<std::string>() == " folded\n");
			YAML_ASSERT(doc[2].to<std::string>() == "keep\n\n");
			YAML_ASSERT(doc[3].to<std::string>() == " strip");
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
			return true;
		}
		
		// 8.2
		TEST BlockIndentationHeader()
		{
			std::string input =
				"- |\n"
				" detected\n"
				"- >\n"
				" \n"
				"  \n"
				"  # detected\n"
				"- |1\n"
				"  explicit\n"
				"- >\n"
				" \t\n"
				" detected\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 4);
1885
1886
1887
1888
			YAML_ASSERT(doc[0].to<std::string>() == "detected\n");
			YAML_ASSERT(doc[1].to<std::string>() == "\n\n# detected\n");
			YAML_ASSERT(doc[2].to<std::string>() == " explicit\n");
			YAML_ASSERT(doc[3].to<std::string>() == "\t\ndetected\n");
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
			return true;
		}
		
		// 8.3
		TEST InvalidBlockScalarIndentationIndicators()
		{
			{
				std::string input =
					"- |\n"
					"  \n"
					" text";
			
				bool threw = false;
				try {
					PARSE(doc, input);
				} catch(const YAML::Exception& e) {
					if(e.msg != YAML::ErrorMsg::END_OF_SEQ)
						throw;
					
					threw = true;
				}
				
				if(!threw)
					return "  no exception thrown for less indented auto-detecting indentation for a literal block scalar";
			}
			
			{
				std::string input =
					"- >\n"
					"  text\n"
					" text";
			
				bool threw = false;
				try {
					PARSE(doc, input);
				} catch(const YAML::Exception& e) {
					if(e.msg != YAML::ErrorMsg::END_OF_SEQ)
						throw;
					
					threw = true;
				}
				
				if(!threw)
					return "  no exception thrown for less indented auto-detecting indentation for a folded block scalar";
			}
			
			{
				std::string input =
					"- |2\n"
					" text";
			
				bool threw = false;
				try {
					PARSE(doc, input);
				} catch(const YAML::Exception& e) {
					if(e.msg != YAML::ErrorMsg::END_OF_SEQ)
						throw;
					
					threw = true;
				}
				
				if(!threw)
					return "  no exception thrown for less indented explicit indentation for a literal block scalar";
			}
			
			return true;
		}
		
		// 8.4
		TEST ChompingFinalLineBreak()
		{
			std::string input =
				"strip: |-\n"
				"  text\n"
				"clip: |\n"
				"  text\n"
				"keep: |+\n"
				"  text\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
1970
1971
1972
			YAML_ASSERT(doc["strip"].to<std::string>() == "text");
			YAML_ASSERT(doc["clip"].to<std::string>() == "text\n");
			YAML_ASSERT(doc["keep"].to<std::string>() == "text\n");
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
			return true;
		}
		
		// 8.5
		TEST ChompingTrailingLines()
		{
			std::string input =
				" # Strip\n"
				"  # Comments:\n"
				"strip: |-\n"
				"  # text\n"
				"  \n"
				" # Clip\n"
				"  # comments:\n"
				"\n"
				"clip: |\n"
				"  # text\n"
				" \n"
				" # Keep\n"
				"  # comments:\n"
				"\n"
				"keep: |+\n"
				"  # text\n"
				"\n"
				" # Trail\n"
				"  # Comments\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
2002
2003
			YAML_ASSERT(doc["strip"].to<std::string>() == "# text");
			YAML_ASSERT(doc["clip"].to<std::string>() == "# text\n");
2004
			YAML_ASSERT(doc["keep"].to<std::string>() == "# text\n"); // Note: I believe this is a bug in the YAML spec - it should be "# text\n\n"
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
			return true;
		}
		
		// 8.6
		TEST EmptyScalarChomping()
		{
			std::string input =
				"strip: >-\n"
				"\n"
				"clip: >\n"
				"\n"
				"keep: |+\n"
				"\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
2021
2022
2023
			YAML_ASSERT(doc["strip"].to<std::string>() == "");
			YAML_ASSERT(doc["clip"].to<std::string>() == "");
			YAML_ASSERT(doc["keep"].to<std::string>() == "\n");
2024
2025
			return true;
		}
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
		
		// 8.7
		TEST LiteralScalar()
		{
			std::string input =
				"|\n"
				" literal\n"
				" \ttext\n"
				"\n";
			
			PARSE(doc, input);
2037
			YAML_ASSERT(doc.to<std::string>() == "literal\n\ttext\n");
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
			return true;
		}
		
		// 8.8
		TEST LiteralContent()
		{
			std::string input =
				"|\n"
				" \n"
				"  \n"
				"  literal\n"
				"   \n"
				"  \n"
				"  text\n"
				"\n"
				" # Comment\n";
			
			PARSE(doc, input);
2056
			YAML_ASSERT(doc.to<std::string>() == "\n\nliteral\n \n\ntext\n");
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
			return true;
		}
		
		// 8.9
		TEST FoldedScalar()
		{
			std::string input =
				">\n"
				" folded\n"
				" text\n"
				"\n";
			
			PARSE(doc, input);
2070
			YAML_ASSERT(doc.to<std::string>() == "folded text\n");
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
			return true;
		}
		
		// 8.10
		TEST FoldedLines()
		{
			std::string input =
				">\n"
				"\n"
				" folded\n"
				" line\n"
				"\n"
				" next\n"
				" line\n"
				"   * bullet\n"
				"\n"
				"   * list\n"
				"   * lines\n"
				"\n"
				" last\n"
				" line\n"
				"\n"
				"# Comment\n";
			
			PARSE(doc, input);
2096
			YAML_ASSERT(doc.to<std::string>() == "\nfolded line\nnext line\n  * bullet\n\n  * list\n  * lines\n\nlast line\n");
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
			return true;
		}
		
		// 8.11
		TEST MoreIndentedLines()
		{
			return true; // same as 8.10
		}
		
		// 8.12
		TEST EmptySeparationLines()
		{
			return true; // same as 8.10
		}
		
		// 8.13
		TEST FinalEmptyLines()
		{
			return true; // same as 8.10
		}
		
		// 8.14
		TEST BlockSequence()
		{
			std::string input =
				"block sequence:\n"
				"  - one\n"
				"  - two : three\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["block sequence"].size() == 2);
2129
			YAML_ASSERT(doc["block sequence"][0].to<std::string>() == "one");
2130
			YAML_ASSERT(doc["block sequence"][1].size() == 1);
2131
			YAML_ASSERT(doc["block sequence"][1]["two"].to<std::string>() == "three");
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
			return true;
		}
		
		// 8.15
		TEST BlockSequenceEntryTypes()
		{
			std::string input =
				"- # Empty\n"
				"- |\n"
				" block node\n"
				"- - one # Compact\n"
				"  - two # sequence\n"
				"- one: two # Compact mapping\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 4);
			YAML_ASSERT(YAML::IsNull(doc[0]));
2149
			YAML_ASSERT(doc[1].to<std::string>() == "block node\n");
2150
			YAML_ASSERT(doc[2].size() == 2);
2151
2152
			YAML_ASSERT(doc[2][0].to<std::string>() == "one");
			YAML_ASSERT(doc[2][1].to<std::string>() == "two");
2153
			YAML_ASSERT(doc[3].size() == 1);
2154
			YAML_ASSERT(doc[3]["one"].to<std::string>() == "two");
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
			return true;
		}
		
		// 8.16
		TEST BlockMappings()
		{
			std::string input =
				"block mapping:\n"
				" key: value\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 1);
			YAML_ASSERT(doc["block mapping"].size() == 1);
2168
			YAML_ASSERT(doc["block mapping"]["key"].to<std::string>() == "value");
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
			return true;
		}
		
		// 8.17
		TEST ExplicitBlockMappingEntries()
		{
			std::string input =
				"? explicit key # Empty value\n"
				"? |\n"
				"  block key\n"
				": - one # Explicit compact\n"
				"  - two # block value\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(IsNull(doc["explicit key"]));
			YAML_ASSERT(doc["block key\n"].size() == 2);
2186
2187
			YAML_ASSERT(doc["block key\n"][0].to<std::string>() == "one");
			YAML_ASSERT(doc["block key\n"][1].to<std::string>() == "two");
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
			return true;
		}
		
		// 8.18
		TEST ImplicitBlockMappingEntries()
		{
			std::string input =
				"plain key: in-line value\n"
				":  # Both empty\n"
				"\"quoted key\":\n"
				"- entry\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
2202
			YAML_ASSERT(doc["plain key"].to<std::string>() == "in-line value");
2203
2204
			YAML_ASSERT(IsNull(doc[YAML::Null]));
			YAML_ASSERT(doc["quoted key"].size() == 1);
2205
			YAML_ASSERT(doc["quoted key"][0].to<std::string>() == "entry");
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
			return true;
		}
		
		// 8.19
		TEST CompactBlockMappings()
		{
			std::string input =
				"- sun: yellow\n"
				"- ? earth: blue\n"
				"  : moon: white\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc[0].size() == 1);
2220
			YAML_ASSERT(doc[0]["sun"].to<std::string>() == "yellow");
2221
2222
2223
2224
			YAML_ASSERT(doc[1].size() == 1);
			std::map<std::string, std::string> key;
			key["earth"] = "blue";
			YAML_ASSERT(doc[1][key].size() == 1);
2225
			YAML_ASSERT(doc[1][key]["moon"].to<std::string>() == "white");
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
			return true;
		}
		
		// 8.20
		TEST BlockNodeTypes()
		{
			std::string input =
				"-\n"
				"  \"flow in block\"\n"
				"- >\n"
				" Block scalar\n"
				"- !!map # Block collection\n"
				"  foo : bar\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 3);
2242
2243
			YAML_ASSERT(doc[0].to<std::string>() == "flow in block");
			YAML_ASSERT(doc[1].to<std::string>() == "Block scalar\n");
2244
			YAML_ASSERT(doc[2].size() == 1);
2245
			YAML_ASSERT(doc[2]["foo"].to<std::string>() == "bar");
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
			return true;
		}
		
		// 8.21
		TEST BlockScalarNodes()
		{
			std::string input =
				"literal: |2\n"
				"  value\n"
				"folded:\n"
				"   !foo\n"
				"  >1\n"
				" value\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
2262
			YAML_ASSERT(doc["literal"].to<std::string>() == "value"); // Note: I believe this is a bug in the YAML spec - it should be "value\n"
2263
			YAML_ASSERT(doc["folded"].to<std::string>() == "value");
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
			YAML_ASSERT(doc["folded"].Tag() == "!foo");
			return true;
		}
		
		// 8.22
		TEST BlockCollectionNodes()
		{
			std::string input =
				"sequence: !!seq\n"
				"- entry\n"
				"- !!seq\n"
				" - nested\n"
				"mapping: !!map\n"
				" foo: bar\n";
			
			PARSE(doc, input);
			YAML_ASSERT(doc.size() == 2);
			YAML_ASSERT(doc["sequence"].size() == 2);
2282
			YAML_ASSERT(doc["sequence"][0].to<std::string>() == "entry");
2283
			YAML_ASSERT(doc["sequence"][1].size() == 1);
2284
			YAML_ASSERT(doc["sequence"][1][0].to<std::string>() == "nested");
2285
			YAML_ASSERT(doc["mapping"].size() == 1);
2286
			YAML_ASSERT(doc["mapping"]["foo"].to<std::string>() == "bar");
2287
2288
			return true;
		}
Jesse Beder's avatar
Jesse Beder committed
2289
2290
	}
}