1//
2// Copyright (c) 2011-2019 Canonical Ltd
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16package yaml_test
17
18import (
19	"bytes"
20	"fmt"
21	"os"
22
23	. "gopkg.in/check.v1"
24	"gopkg.in/yaml.v3"
25	"io"
26	"strings"
27)
28
29var nodeTests = []struct {
30	yaml string
31	node yaml.Node
32}{
33	{
34		"null\n",
35		yaml.Node{
36			Kind:   yaml.DocumentNode,
37			Line:   1,
38			Column: 1,
39			Content: []*yaml.Node{{
40				Kind:   yaml.ScalarNode,
41				Value:  "null",
42				Tag:    "!!null",
43				Line:   1,
44				Column: 1,
45			}},
46		},
47	}, {
48		"[encode]null\n",
49		yaml.Node{},
50	}, {
51		"foo\n",
52		yaml.Node{
53			Kind:   yaml.DocumentNode,
54			Line:   1,
55			Column: 1,
56			Content: []*yaml.Node{{
57				Kind:   yaml.ScalarNode,
58				Value:  "foo",
59				Tag:    "!!str",
60				Line:   1,
61				Column: 1,
62			}},
63		},
64	}, {
65		"\"foo\"\n",
66		yaml.Node{
67			Kind:   yaml.DocumentNode,
68			Line:   1,
69			Column: 1,
70			Content: []*yaml.Node{{
71				Kind:   yaml.ScalarNode,
72				Style:  yaml.DoubleQuotedStyle,
73				Value:  "foo",
74				Tag:    "!!str",
75				Line:   1,
76				Column: 1,
77			}},
78		},
79	}, {
80		"'foo'\n",
81		yaml.Node{
82			Kind:   yaml.DocumentNode,
83			Line:   1,
84			Column: 1,
85			Content: []*yaml.Node{{
86				Kind:   yaml.ScalarNode,
87				Style:  yaml.SingleQuotedStyle,
88				Value:  "foo",
89				Tag:    "!!str",
90				Line:   1,
91				Column: 1,
92			}},
93		},
94	}, {
95		"!!str 123\n",
96		yaml.Node{
97			Kind:   yaml.DocumentNode,
98			Line:   1,
99			Column: 1,
100			Content: []*yaml.Node{{
101				Kind:   yaml.ScalarNode,
102				Style:  yaml.TaggedStyle,
103				Value:  "123",
104				Tag:    "!!str",
105				Line:   1,
106				Column: 1,
107			}},
108		},
109	}, {
110		// Although the node isn't TaggedStyle, dropping the tag would change the value.
111		"[encode]!!binary gIGC\n",
112		yaml.Node{
113			Kind:   yaml.DocumentNode,
114			Line:   1,
115			Column: 1,
116			Content: []*yaml.Node{{
117				Kind:   yaml.ScalarNode,
118				Value:  "gIGC",
119				Tag:    "!!binary",
120				Line:   1,
121				Column: 1,
122			}},
123		},
124	}, {
125		// Item doesn't have a tag, but needs to be binary encoded due to its content.
126		"[encode]!!binary gIGC\n",
127		yaml.Node{
128			Kind:   yaml.DocumentNode,
129			Line:   1,
130			Column: 1,
131			Content: []*yaml.Node{{
132				Kind:   yaml.ScalarNode,
133				Value:  "\x80\x81\x82",
134				Line:   1,
135				Column: 1,
136			}},
137		},
138	}, {
139		// Same, but with strings we can just quote them.
140		"[encode]\"123\"\n",
141		yaml.Node{
142			Kind:   yaml.DocumentNode,
143			Line:   1,
144			Column: 1,
145			Content: []*yaml.Node{{
146				Kind:   yaml.ScalarNode,
147				Value:  "123",
148				Tag:    "!!str",
149				Line:   1,
150				Column: 1,
151			}},
152		},
153	}, {
154		"!tag:something 123\n",
155		yaml.Node{
156			Kind:   yaml.DocumentNode,
157			Line:   1,
158			Column: 1,
159			Content: []*yaml.Node{{
160				Kind:   yaml.ScalarNode,
161				Style:  yaml.TaggedStyle,
162				Value:  "123",
163				Tag:    "!tag:something",
164				Line:   1,
165				Column: 1,
166			}},
167		},
168	}, {
169		"[encode]!tag:something 123\n",
170		yaml.Node{
171			Kind:   yaml.DocumentNode,
172			Line:   1,
173			Column: 1,
174			Content: []*yaml.Node{{
175				Kind:   yaml.ScalarNode,
176				Value:  "123",
177				Tag:    "!tag:something",
178				Line:   1,
179				Column: 1,
180			}},
181		},
182	}, {
183		"!tag:something {}\n",
184		yaml.Node{
185			Kind:   yaml.DocumentNode,
186			Line:   1,
187			Column: 1,
188			Content: []*yaml.Node{{
189				Kind:   yaml.MappingNode,
190				Style:  yaml.TaggedStyle | yaml.FlowStyle,
191				Tag:    "!tag:something",
192				Line:   1,
193				Column: 1,
194			}},
195		},
196	}, {
197		"[encode]!tag:something {}\n",
198		yaml.Node{
199			Kind:   yaml.DocumentNode,
200			Line:   1,
201			Column: 1,
202			Content: []*yaml.Node{{
203				Kind:   yaml.MappingNode,
204				Style:  yaml.FlowStyle,
205				Tag:    "!tag:something",
206				Line:   1,
207				Column: 1,
208			}},
209		},
210	}, {
211		"!tag:something []\n",
212		yaml.Node{
213			Kind:   yaml.DocumentNode,
214			Line:   1,
215			Column: 1,
216			Content: []*yaml.Node{{
217				Kind:   yaml.SequenceNode,
218				Style:  yaml.TaggedStyle | yaml.FlowStyle,
219				Tag:    "!tag:something",
220				Line:   1,
221				Column: 1,
222			}},
223		},
224	}, {
225		"[encode]!tag:something []\n",
226		yaml.Node{
227			Kind:   yaml.DocumentNode,
228			Line:   1,
229			Column: 1,
230			Content: []*yaml.Node{{
231				Kind:   yaml.SequenceNode,
232				Style:  yaml.FlowStyle,
233				Tag:    "!tag:something",
234				Line:   1,
235				Column: 1,
236			}},
237		},
238	}, {
239		"''\n",
240		yaml.Node{
241			Kind:   yaml.DocumentNode,
242			Line:   1,
243			Column: 1,
244			Content: []*yaml.Node{{
245				Kind:   yaml.ScalarNode,
246				Style:  yaml.SingleQuotedStyle,
247				Value:  "",
248				Tag:    "!!str",
249				Line:   1,
250				Column: 1,
251			}},
252		},
253	}, {
254		"|\n  foo\n  bar\n",
255		yaml.Node{
256			Kind:   yaml.DocumentNode,
257			Line:   1,
258			Column: 1,
259			Content: []*yaml.Node{{
260				Kind:   yaml.ScalarNode,
261				Style:  yaml.LiteralStyle,
262				Value:  "foo\nbar\n",
263				Tag:    "!!str",
264				Line:   1,
265				Column: 1,
266			}},
267		},
268	}, {
269		"true\n",
270		yaml.Node{
271			Kind:   yaml.DocumentNode,
272			Line:   1,
273			Column: 1,
274			Content: []*yaml.Node{{
275				Kind:   yaml.ScalarNode,
276				Value:  "true",
277				Tag:    "!!bool",
278				Line:   1,
279				Column: 1,
280			}},
281		},
282	}, {
283		"-10\n",
284		yaml.Node{
285			Kind:   yaml.DocumentNode,
286			Line:   1,
287			Column: 1,
288			Content: []*yaml.Node{{
289				Kind:   yaml.ScalarNode,
290				Value:  "-10",
291				Tag:    "!!int",
292				Line:   1,
293				Column: 1,
294			}},
295		},
296	}, {
297		"4294967296\n",
298		yaml.Node{
299			Kind:   yaml.DocumentNode,
300			Line:   1,
301			Column: 1,
302			Content: []*yaml.Node{{
303				Kind:   yaml.ScalarNode,
304				Value:  "4294967296",
305				Tag:    "!!int",
306				Line:   1,
307				Column: 1,
308			}},
309		},
310	}, {
311		"0.1000\n",
312		yaml.Node{
313			Kind:   yaml.DocumentNode,
314			Line:   1,
315			Column: 1,
316			Content: []*yaml.Node{{
317				Kind:   yaml.ScalarNode,
318				Value:  "0.1000",
319				Tag:    "!!float",
320				Line:   1,
321				Column: 1,
322			}},
323		},
324	}, {
325		"-.inf\n",
326		yaml.Node{
327			Kind:   yaml.DocumentNode,
328			Line:   1,
329			Column: 1,
330			Content: []*yaml.Node{{
331				Kind:   yaml.ScalarNode,
332				Value:  "-.inf",
333				Tag:    "!!float",
334				Line:   1,
335				Column: 1,
336			}},
337		},
338	}, {
339		".nan\n",
340		yaml.Node{
341			Kind:   yaml.DocumentNode,
342			Line:   1,
343			Column: 1,
344			Content: []*yaml.Node{{
345				Kind:   yaml.ScalarNode,
346				Value:  ".nan",
347				Tag:    "!!float",
348				Line:   1,
349				Column: 1,
350			}},
351		},
352	}, {
353		"{}\n",
354		yaml.Node{
355			Kind:   yaml.DocumentNode,
356			Line:   1,
357			Column: 1,
358			Content: []*yaml.Node{{
359				Kind:   yaml.MappingNode,
360				Style:  yaml.FlowStyle,
361				Value:  "",
362				Tag:    "!!map",
363				Line:   1,
364				Column: 1,
365			}},
366		},
367	}, {
368		"a: b c\n",
369		yaml.Node{
370			Kind:   yaml.DocumentNode,
371			Line:   1,
372			Column: 1,
373			Content: []*yaml.Node{{
374				Kind:   yaml.MappingNode,
375				Value:  "",
376				Tag:    "!!map",
377				Line:   1,
378				Column: 1,
379				Content: []*yaml.Node{{
380					Kind:   yaml.ScalarNode,
381					Value:  "a",
382					Tag:    "!!str",
383					Line:   1,
384					Column: 1,
385				}, {
386					Kind:   yaml.ScalarNode,
387					Value:  "b c",
388					Tag:    "!!str",
389					Line:   1,
390					Column: 4,
391				}},
392			}},
393		},
394	}, {
395		"a:\n  b: c\n  d: e\n",
396		yaml.Node{
397			Kind:   yaml.DocumentNode,
398			Line:   1,
399			Column: 1,
400			Content: []*yaml.Node{{
401				Kind:   yaml.MappingNode,
402				Tag:    "!!map",
403				Line:   1,
404				Column: 1,
405				Content: []*yaml.Node{{
406					Kind:   yaml.ScalarNode,
407					Value:  "a",
408					Tag:    "!!str",
409					Line:   1,
410					Column: 1,
411				}, {
412					Kind:   yaml.MappingNode,
413					Tag:    "!!map",
414					Line:   2,
415					Column: 3,
416					Content: []*yaml.Node{{
417						Kind:   yaml.ScalarNode,
418						Value:  "b",
419						Tag:    "!!str",
420						Line:   2,
421						Column: 3,
422					}, {
423						Kind:   yaml.ScalarNode,
424						Value:  "c",
425						Tag:    "!!str",
426						Line:   2,
427						Column: 6,
428					}, {
429						Kind:   yaml.ScalarNode,
430						Value:  "d",
431						Tag:    "!!str",
432						Line:   3,
433						Column: 3,
434					}, {
435						Kind:   yaml.ScalarNode,
436						Value:  "e",
437						Tag:    "!!str",
438						Line:   3,
439						Column: 6,
440					}},
441				}},
442			}},
443		},
444	}, {
445		"a:\n  - b: c\n    d: e\n",
446		yaml.Node{
447			Kind:   yaml.DocumentNode,
448			Line:   1,
449			Column: 1,
450			Content: []*yaml.Node{{
451				Kind:   yaml.MappingNode,
452				Tag:    "!!map",
453				Line:   1,
454				Column: 1,
455				Content: []*yaml.Node{{
456					Kind:   yaml.ScalarNode,
457					Value:  "a",
458					Tag:    "!!str",
459					Line:   1,
460					Column: 1,
461				}, {
462					Kind:   yaml.SequenceNode,
463					Tag:    "!!seq",
464					Line:   2,
465					Column: 3,
466					Content: []*yaml.Node{{
467						Kind:   yaml.MappingNode,
468						Tag:    "!!map",
469						Line:   2,
470						Column: 5,
471						Content: []*yaml.Node{{
472							Kind:   yaml.ScalarNode,
473							Value:  "b",
474							Tag:    "!!str",
475							Line:   2,
476							Column: 5,
477						}, {
478							Kind:   yaml.ScalarNode,
479							Value:  "c",
480							Tag:    "!!str",
481							Line:   2,
482							Column: 8,
483						}, {
484							Kind:   yaml.ScalarNode,
485							Value:  "d",
486							Tag:    "!!str",
487							Line:   3,
488							Column: 5,
489						}, {
490							Kind:   yaml.ScalarNode,
491							Value:  "e",
492							Tag:    "!!str",
493							Line:   3,
494							Column: 8,
495						}},
496					}},
497				}},
498			}},
499		},
500	}, {
501		"a: # AI\n  - b\nc:\n  - d\n",
502		yaml.Node{
503			Kind:   yaml.DocumentNode,
504			Line:   1,
505			Column: 1,
506			Content: []*yaml.Node{{
507				Kind:   yaml.MappingNode,
508				Tag:    "!!map",
509				Line:   1,
510				Column: 1,
511				Content: []*yaml.Node{{
512					Kind:        yaml.ScalarNode,
513					Tag:         "!!str",
514					Value:       "a",
515					LineComment: "# AI",
516					Line:        1,
517					Column:      1,
518				}, {
519					Kind: yaml.SequenceNode,
520					Tag:  "!!seq",
521					Content: []*yaml.Node{{
522						Kind:   yaml.ScalarNode,
523						Tag:    "!!str",
524						Value:  "b",
525						Line:   2,
526						Column: 5,
527					}},
528					Line:   2,
529					Column: 3,
530				}, {
531					Kind:   yaml.ScalarNode,
532					Tag:    "!!str",
533					Value:  "c",
534					Line:   3,
535					Column: 1,
536				}, {
537					Kind: yaml.SequenceNode,
538					Tag:  "!!seq",
539					Content: []*yaml.Node{{
540						Kind:   yaml.ScalarNode,
541						Tag:    "!!str",
542						Value:  "d",
543						Line:   4,
544						Column: 5,
545					}},
546					Line:   4,
547					Column: 3,
548				}},
549			}},
550		},
551	}, {
552		"[decode]a:\n  # HM\n  - # HB1\n    # HB2\n    b: # IB\n      c # IC\n",
553		yaml.Node{
554			Kind:   yaml.DocumentNode,
555			Line:   1,
556			Column: 1,
557			Content: []*yaml.Node{{
558				Kind:   yaml.MappingNode,
559				Tag:    "!!map",
560				Line:   1,
561				Column: 1,
562				Content: []*yaml.Node{{
563					Kind:   yaml.ScalarNode,
564					Style:  0x0,
565					Tag:    "!!str",
566					Value:  "a",
567					Line:   1,
568					Column: 1,
569				}, {
570					Kind:   yaml.SequenceNode,
571					Tag:    "!!seq",
572					Line:   3,
573					Column: 3,
574					Content: []*yaml.Node{{
575						Kind:        yaml.MappingNode,
576						Tag:         "!!map",
577						HeadComment: "# HM",
578						Line:        5,
579						Column:      5,
580						Content: []*yaml.Node{{
581							Kind:        yaml.ScalarNode,
582							Tag:         "!!str",
583							Value:       "b",
584							HeadComment: "# HB1\n# HB2",
585							LineComment: "# IB",
586							Line:        5,
587							Column:      5,
588						}, {
589							Kind:        yaml.ScalarNode,
590							Tag:         "!!str",
591							Value:       "c",
592							LineComment: "# IC",
593							Line:        6,
594							Column:      7,
595						}},
596					}},
597				}},
598			}},
599		},
600	}, {
601		// When encoding the value above, it loses b's inline comment.
602		"[encode]a:\n  # HM\n  - # HB1\n    # HB2\n    b: c # IC\n",
603		yaml.Node{
604			Kind:   yaml.DocumentNode,
605			Line:   1,
606			Column: 1,
607			Content: []*yaml.Node{{
608				Kind:   yaml.MappingNode,
609				Tag:    "!!map",
610				Line:   1,
611				Column: 1,
612				Content: []*yaml.Node{{
613					Kind:   yaml.ScalarNode,
614					Style:  0x0,
615					Tag:    "!!str",
616					Value:  "a",
617					Line:   1,
618					Column: 1,
619				}, {
620					Kind:   yaml.SequenceNode,
621					Tag:    "!!seq",
622					Line:   3,
623					Column: 3,
624					Content: []*yaml.Node{{
625						Kind:        yaml.MappingNode,
626						Tag:         "!!map",
627						HeadComment: "# HM",
628						Line:        5,
629						Column:      5,
630						Content: []*yaml.Node{{
631							Kind:        yaml.ScalarNode,
632							Tag:         "!!str",
633							Value:       "b",
634							HeadComment: "# HB1\n# HB2",
635							LineComment: "# IB",
636							Line:        5,
637							Column:      5,
638						}, {
639							Kind:        yaml.ScalarNode,
640							Tag:         "!!str",
641							Value:       "c",
642							LineComment: "# IC",
643							Line:        6,
644							Column:      7,
645						}},
646					}},
647				}},
648			}},
649		},
650	}, {
651		// Multiple cases of comment inlining next to mapping keys.
652		"a: | # IA\n  str\nb: >- # IB\n  str\nc: # IC\n  - str\nd: # ID\n  str:\n",
653		yaml.Node{
654			Kind:   yaml.DocumentNode,
655			Line:   1,
656			Column: 1,
657			Content: []*yaml.Node{{
658				Kind:   yaml.MappingNode,
659				Tag:    "!!map",
660				Line:   1,
661				Column: 1,
662				Content: []*yaml.Node{{
663					Kind:   yaml.ScalarNode,
664					Tag:    "!!str",
665					Value:  "a",
666					Line:   1,
667					Column: 1,
668				}, {
669					Kind:        yaml.ScalarNode,
670					Style:       yaml.LiteralStyle,
671					Tag:         "!!str",
672					Value:       "str\n",
673					LineComment: "# IA",
674					Line:        1,
675					Column:      4,
676				}, {
677					Kind:   yaml.ScalarNode,
678					Tag:    "!!str",
679					Value:  "b",
680					Line:   3,
681					Column: 1,
682				}, {
683					Kind:        yaml.ScalarNode,
684					Style:       yaml.FoldedStyle,
685					Tag:         "!!str",
686					Value:       "str",
687					LineComment: "# IB",
688					Line:        3,
689					Column:      4,
690				}, {
691					Kind:   yaml.ScalarNode,
692					Tag:    "!!str",
693					Value:  "c",
694					LineComment: "# IC",
695					Line:   5,
696					Column: 1,
697				}, {
698					Kind:        yaml.SequenceNode,
699					Tag:         "!!seq",
700					Line:        6,
701					Column:      3,
702					Content: []*yaml.Node{{
703						Kind:   yaml.ScalarNode,
704						Tag:    "!!str",
705						Value:  "str",
706						Line:   6,
707						Column: 5,
708					}},
709				}, {
710					Kind:   yaml.ScalarNode,
711					Tag:    "!!str",
712					Value:  "d",
713					LineComment: "# ID",
714					Line:   7,
715					Column: 1,
716				}, {
717					Kind:        yaml.MappingNode,
718					Tag:         "!!map",
719					Line:        8,
720					Column:      3,
721					Content: []*yaml.Node{{
722						Kind:   yaml.ScalarNode,
723						Tag:    "!!str",
724						Value:  "str",
725						Line:   8,
726						Column: 3,
727					}, {
728						Kind:   yaml.ScalarNode,
729						Tag:    "!!null",
730						Line:   8,
731						Column: 7,
732					}},
733				}},
734			}},
735		},
736	}, {
737		// Indentless sequence.
738		"[decode]a:\n# HM\n- # HB1\n  # HB2\n  b: # IB\n    c # IC\n",
739		yaml.Node{
740			Kind:   yaml.DocumentNode,
741			Line:   1,
742			Column: 1,
743			Content: []*yaml.Node{{
744				Kind:   yaml.MappingNode,
745				Tag:    "!!map",
746				Line:   1,
747				Column: 1,
748				Content: []*yaml.Node{{
749					Kind:   yaml.ScalarNode,
750					Tag:    "!!str",
751					Value:  "a",
752					Line:   1,
753					Column: 1,
754				}, {
755					Kind:   yaml.SequenceNode,
756					Tag:    "!!seq",
757					Line:   3,
758					Column: 1,
759					Content: []*yaml.Node{{
760						Kind:        yaml.MappingNode,
761						Tag:         "!!map",
762						HeadComment: "# HM",
763						Line:        5,
764						Column:      3,
765						Content: []*yaml.Node{{
766							Kind:        yaml.ScalarNode,
767							Tag:         "!!str",
768							Value:       "b",
769							HeadComment: "# HB1\n# HB2",
770							LineComment: "# IB",
771							Line:        5,
772							Column:      3,
773						}, {
774							Kind:        yaml.ScalarNode,
775							Tag:         "!!str",
776							Value:       "c",
777							LineComment: "# IC",
778							Line:        6,
779							Column:      5,
780						}},
781					}},
782				}},
783			}},
784		},
785	}, {
786		"- a\n- b\n",
787		yaml.Node{
788			Kind:   yaml.DocumentNode,
789			Line:   1,
790			Column: 1,
791			Content: []*yaml.Node{{
792				Kind:   yaml.SequenceNode,
793				Value:  "",
794				Tag:    "!!seq",
795				Line:   1,
796				Column: 1,
797				Content: []*yaml.Node{{
798					Kind:   yaml.ScalarNode,
799					Value:  "a",
800					Tag:    "!!str",
801					Line:   1,
802					Column: 3,
803				}, {
804					Kind:   yaml.ScalarNode,
805					Value:  "b",
806					Tag:    "!!str",
807					Line:   2,
808					Column: 3,
809				}},
810			}},
811		},
812	}, {
813		"- a\n- - b\n  - c\n",
814		yaml.Node{
815			Kind:   yaml.DocumentNode,
816			Line:   1,
817			Column: 1,
818			Content: []*yaml.Node{{
819				Kind:   yaml.SequenceNode,
820				Tag:    "!!seq",
821				Line:   1,
822				Column: 1,
823				Content: []*yaml.Node{{
824					Kind:   yaml.ScalarNode,
825					Value:  "a",
826					Tag:    "!!str",
827					Line:   1,
828					Column: 3,
829				}, {
830					Kind:   yaml.SequenceNode,
831					Tag:    "!!seq",
832					Line:   2,
833					Column: 3,
834					Content: []*yaml.Node{{
835						Kind:   yaml.ScalarNode,
836						Value:  "b",
837						Tag:    "!!str",
838						Line:   2,
839						Column: 5,
840					}, {
841						Kind:   yaml.ScalarNode,
842						Value:  "c",
843						Tag:    "!!str",
844						Line:   3,
845						Column: 5,
846					}},
847				}},
848			}},
849		},
850	}, {
851		"[a, b]\n",
852		yaml.Node{
853			Kind:   yaml.DocumentNode,
854			Line:   1,
855			Column: 1,
856			Content: []*yaml.Node{{
857				Kind:   yaml.SequenceNode,
858				Style:  yaml.FlowStyle,
859				Value:  "",
860				Tag:    "!!seq",
861				Line:   1,
862				Column: 1,
863				Content: []*yaml.Node{{
864					Kind:   yaml.ScalarNode,
865					Value:  "a",
866					Tag:    "!!str",
867					Line:   1,
868					Column: 2,
869				}, {
870					Kind:   yaml.ScalarNode,
871					Value:  "b",
872					Tag:    "!!str",
873					Line:   1,
874					Column: 5,
875				}},
876			}},
877		},
878	}, {
879		"- a\n- [b, c]\n",
880		yaml.Node{
881			Kind:   yaml.DocumentNode,
882			Line:   1,
883			Column: 1,
884			Content: []*yaml.Node{{
885				Kind:   yaml.SequenceNode,
886				Tag:    "!!seq",
887				Line:   1,
888				Column: 1,
889				Content: []*yaml.Node{{
890					Kind:   yaml.ScalarNode,
891					Value:  "a",
892					Tag:    "!!str",
893					Line:   1,
894					Column: 3,
895				}, {
896					Kind:   yaml.SequenceNode,
897					Tag:    "!!seq",
898					Style:  yaml.FlowStyle,
899					Line:   2,
900					Column: 3,
901					Content: []*yaml.Node{{
902						Kind:   yaml.ScalarNode,
903						Value:  "b",
904						Tag:    "!!str",
905						Line:   2,
906						Column: 4,
907					}, {
908						Kind:   yaml.ScalarNode,
909						Value:  "c",
910						Tag:    "!!str",
911						Line:   2,
912						Column: 7,
913					}},
914				}},
915			}},
916		},
917	}, {
918		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
919		yaml.Node{
920			Kind:   yaml.DocumentNode,
921			Line:   1,
922			Column: 1,
923			Content: []*yaml.Node{{
924				Kind:   yaml.MappingNode,
925				Line:   1,
926				Column: 1,
927				Tag:    "!!map",
928				Content: []*yaml.Node{{
929					Kind:   yaml.ScalarNode,
930					Value:  "a",
931					Tag:    "!!str",
932					Line:   1,
933					Column: 1,
934				},
935					saveNode("x", &yaml.Node{
936						Kind:   yaml.ScalarNode,
937						Value:  "1",
938						Tag:    "!!int",
939						Anchor: "x",
940						Line:   1,
941						Column: 4,
942					}),
943					{
944						Kind:   yaml.ScalarNode,
945						Value:  "b",
946						Tag:    "!!str",
947						Line:   2,
948						Column: 1,
949					},
950					saveNode("y", &yaml.Node{
951						Kind:   yaml.ScalarNode,
952						Value:  "2",
953						Tag:    "!!int",
954						Anchor: "y",
955						Line:   2,
956						Column: 4,
957					}),
958					{
959						Kind:   yaml.ScalarNode,
960						Value:  "c",
961						Tag:    "!!str",
962						Line:   3,
963						Column: 1,
964					}, {
965						Kind:   yaml.AliasNode,
966						Value:  "x",
967						Alias:  dropNode("x"),
968						Line:   3,
969						Column: 4,
970					}, {
971						Kind:   yaml.ScalarNode,
972						Value:  "d",
973						Tag:    "!!str",
974						Line:   4,
975						Column: 1,
976					}, {
977						Kind:   yaml.AliasNode,
978						Value:  "y",
979						Tag:    "",
980						Alias:  dropNode("y"),
981						Line:   4,
982						Column: 4,
983					}},
984			}},
985		},
986	}, {
987
988		"# One\n# Two\ntrue # Three\n# Four\n# Five\n",
989		yaml.Node{
990			Kind:   yaml.DocumentNode,
991			Line:   3,
992			Column: 1,
993			Content: []*yaml.Node{{
994				Kind:        yaml.ScalarNode,
995				Value:       "true",
996				Tag:         "!!bool",
997				Line:        3,
998				Column:      1,
999				HeadComment: "# One\n# Two",
1000				LineComment: "# Three",
1001				FootComment: "# Four\n# Five",
1002			}},
1003		},
1004	}, {
1005
1006		"# š\ntrue # š\n",
1007		yaml.Node{
1008			Kind:   yaml.DocumentNode,
1009			Line:   2,
1010			Column: 1,
1011			Content: []*yaml.Node{{
1012				Kind:        yaml.ScalarNode,
1013				Value:       "true",
1014				Tag:         "!!bool",
1015				Line:        2,
1016				Column:      1,
1017				HeadComment: "# š",
1018				LineComment: "# š",
1019			}},
1020		},
1021	}, {
1022
1023		"[decode]\n# One\n\n# Two\n\n# Three\ntrue # Four\n# Five\n\n# Six\n\n# Seven\n",
1024		yaml.Node{
1025			Kind:        yaml.DocumentNode,
1026			Line:        7,
1027			Column:      1,
1028			HeadComment: "# One\n\n# Two",
1029			FootComment: "# Six\n\n# Seven",
1030			Content: []*yaml.Node{{
1031				Kind:        yaml.ScalarNode,
1032				Value:       "true",
1033				Tag:         "!!bool",
1034				Line:        7,
1035				Column:      1,
1036				HeadComment: "# Three",
1037				LineComment: "# Four",
1038				FootComment: "# Five",
1039			}},
1040		},
1041	}, {
1042		// Write out the pound character if missing from comments.
1043		"[encode]# One\n# Two\ntrue # Three\n# Four\n# Five\n",
1044		yaml.Node{
1045			Kind:   yaml.DocumentNode,
1046			Line:   3,
1047			Column: 1,
1048			Content: []*yaml.Node{{
1049				Kind:        yaml.ScalarNode,
1050				Value:       "true",
1051				Tag:         "!!bool",
1052				Line:        3,
1053				Column:      1,
1054				HeadComment: "One\nTwo\n",
1055				LineComment: "Three\n",
1056				FootComment: "Four\nFive\n",
1057			}},
1058		},
1059	}, {
1060		"[encode]#   One\n#   Two\ntrue #   Three\n#   Four\n#   Five\n",
1061		yaml.Node{
1062			Kind:   yaml.DocumentNode,
1063			Line:   3,
1064			Column: 1,
1065			Content: []*yaml.Node{{
1066				Kind:        yaml.ScalarNode,
1067				Value:       "true",
1068				Tag:         "!!bool",
1069				Line:        3,
1070				Column:      1,
1071				HeadComment: "  One\n  Two",
1072				LineComment: "  Three",
1073				FootComment: "  Four\n  Five",
1074			}},
1075		},
1076	}, {
1077		"# DH1\n\n# DH2\n\n# H1\n# H2\ntrue # I\n# F1\n# F2\n\n# DF1\n\n# DF2\n",
1078		yaml.Node{
1079			Kind:        yaml.DocumentNode,
1080			Line:        7,
1081			Column:      1,
1082			HeadComment: "# DH1\n\n# DH2",
1083			FootComment: "# DF1\n\n# DF2",
1084			Content: []*yaml.Node{{
1085				Kind:        yaml.ScalarNode,
1086				Value:       "true",
1087				Tag:         "!!bool",
1088				Line:        7,
1089				Column:      1,
1090				HeadComment: "# H1\n# H2",
1091				LineComment: "# I",
1092				FootComment: "# F1\n# F2",
1093			}},
1094		},
1095	}, {
1096		"# DH1\n\n# DH2\n\n# HA1\n# HA2\nka: va # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\nkb: vb # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n",
1097		yaml.Node{
1098			Kind:        yaml.DocumentNode,
1099			Line:        7,
1100			Column:      1,
1101			HeadComment: "# DH1\n\n# DH2",
1102			FootComment: "# DF1\n\n# DF2",
1103			Content: []*yaml.Node{{
1104				Kind:   yaml.MappingNode,
1105				Tag:    "!!map",
1106				Line:   7,
1107				Column: 1,
1108				Content: []*yaml.Node{{
1109					Kind:        yaml.ScalarNode,
1110					Line:        7,
1111					Column:      1,
1112					Tag:         "!!str",
1113					Value:       "ka",
1114					HeadComment: "# HA1\n# HA2",
1115					FootComment: "# FA1\n# FA2",
1116				}, {
1117					Kind:        yaml.ScalarNode,
1118					Line:        7,
1119					Column:      5,
1120					Tag:         "!!str",
1121					Value:       "va",
1122					LineComment: "# IA",
1123				}, {
1124					Kind:        yaml.ScalarNode,
1125					Line:        13,
1126					Column:      1,
1127					Tag:         "!!str",
1128					Value:       "kb",
1129					HeadComment: "# HB1\n# HB2",
1130					FootComment: "# FB1\n# FB2",
1131				}, {
1132					Kind:        yaml.ScalarNode,
1133					Line:        13,
1134					Column:      5,
1135					Tag:         "!!str",
1136					Value:       "vb",
1137					LineComment: "# IB",
1138				}},
1139			}},
1140		},
1141	}, {
1142		"# DH1\n\n# DH2\n\n# HA1\n# HA2\n- la # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\n- lb # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n",
1143		yaml.Node{
1144			Kind:        yaml.DocumentNode,
1145			Line:        7,
1146			Column:      1,
1147			HeadComment: "# DH1\n\n# DH2",
1148			FootComment: "# DF1\n\n# DF2",
1149			Content: []*yaml.Node{{
1150				Kind:   yaml.SequenceNode,
1151				Tag:    "!!seq",
1152				Line:   7,
1153				Column: 1,
1154				Content: []*yaml.Node{{
1155					Kind:        yaml.ScalarNode,
1156					Tag:         "!!str",
1157					Line:        7,
1158					Column:      3,
1159					Value:       "la",
1160					HeadComment: "# HA1\n# HA2",
1161					LineComment: "# IA",
1162					FootComment: "# FA1\n# FA2",
1163				}, {
1164					Kind:        yaml.ScalarNode,
1165					Tag:         "!!str",
1166					Line:        13,
1167					Column:      3,
1168					Value:       "lb",
1169					HeadComment: "# HB1\n# HB2",
1170					LineComment: "# IB",
1171					FootComment: "# FB1\n# FB2",
1172				}},
1173			}},
1174		},
1175	}, {
1176		"# DH1\n\n- la # IA\n# HB1\n- lb\n",
1177		yaml.Node{
1178			Kind:        yaml.DocumentNode,
1179			Line:        3,
1180			Column:      1,
1181			HeadComment: "# DH1",
1182			Content: []*yaml.Node{{
1183				Kind:   yaml.SequenceNode,
1184				Tag:    "!!seq",
1185				Line:   3,
1186				Column: 1,
1187				Content: []*yaml.Node{{
1188					Kind:        yaml.ScalarNode,
1189					Tag:         "!!str",
1190					Line:        3,
1191					Column:      3,
1192					Value:       "la",
1193					LineComment: "# IA",
1194				}, {
1195					Kind:        yaml.ScalarNode,
1196					Tag:         "!!str",
1197					Line:        5,
1198					Column:      3,
1199					Value:       "lb",
1200					HeadComment: "# HB1",
1201				}},
1202			}},
1203		},
1204	}, {
1205		"- la # IA\n- lb # IB\n- lc # IC\n",
1206		yaml.Node{
1207			Kind:   yaml.DocumentNode,
1208			Line:   1,
1209			Column: 1,
1210			Content: []*yaml.Node{{
1211				Kind:   yaml.SequenceNode,
1212				Tag:    "!!seq",
1213				Line:   1,
1214				Column: 1,
1215				Content: []*yaml.Node{{
1216					Kind:        yaml.ScalarNode,
1217					Tag:         "!!str",
1218					Line:        1,
1219					Column:      3,
1220					Value:       "la",
1221					LineComment: "# IA",
1222				}, {
1223					Kind:        yaml.ScalarNode,
1224					Tag:         "!!str",
1225					Line:        2,
1226					Column:      3,
1227					Value:       "lb",
1228					LineComment: "# IB",
1229				}, {
1230					Kind:        yaml.ScalarNode,
1231					Tag:         "!!str",
1232					Line:        3,
1233					Column:      3,
1234					Value:       "lc",
1235					LineComment: "# IC",
1236				}},
1237			}},
1238		},
1239	}, {
1240		"# DH1\n\n# HL1\n- - la\n  # HB1\n  - lb\n",
1241		yaml.Node{
1242			Kind:        yaml.DocumentNode,
1243			Line:        4,
1244			Column:      1,
1245			HeadComment: "# DH1",
1246			Content: []*yaml.Node{{
1247				Kind:   yaml.SequenceNode,
1248				Tag:    "!!seq",
1249				Line:   4,
1250				Column: 1,
1251				Content: []*yaml.Node{{
1252					Kind:        yaml.SequenceNode,
1253					Tag:         "!!seq",
1254					Line:        4,
1255					Column:      3,
1256					HeadComment: "# HL1",
1257					Content: []*yaml.Node{{
1258						Kind:   yaml.ScalarNode,
1259						Tag:    "!!str",
1260						Line:   4,
1261						Column: 5,
1262						Value:  "la",
1263					}, {
1264						Kind:        yaml.ScalarNode,
1265						Tag:         "!!str",
1266						Line:        6,
1267						Column:      5,
1268						Value:       "lb",
1269						HeadComment: "# HB1",
1270					}},
1271				}},
1272			}},
1273		},
1274	}, {
1275		"# DH1\n\n# HL1\n- # HA1\n  - la\n  # HB1\n  - lb\n",
1276		yaml.Node{
1277			Kind:        yaml.DocumentNode,
1278			Line:        4,
1279			Column:      1,
1280			HeadComment: "# DH1",
1281			Content: []*yaml.Node{{
1282				Kind:   yaml.SequenceNode,
1283				Tag:    "!!seq",
1284				Line:   4,
1285				Column: 1,
1286				Content: []*yaml.Node{{
1287					Kind:        yaml.SequenceNode,
1288					Tag:         "!!seq",
1289					Line:        5,
1290					Column:      3,
1291					HeadComment: "# HL1",
1292					Content: []*yaml.Node{{
1293						Kind:        yaml.ScalarNode,
1294						Tag:         "!!str",
1295						Line:        5,
1296						Column:      5,
1297						Value:       "la",
1298						HeadComment: "# HA1",
1299					}, {
1300						Kind:        yaml.ScalarNode,
1301						Tag:         "!!str",
1302						Line:        7,
1303						Column:      5,
1304						Value:       "lb",
1305						HeadComment: "# HB1",
1306					}},
1307				}},
1308			}},
1309		},
1310	}, {
1311		"[decode]# DH1\n\n# HL1\n- # HA1\n\n  - la\n  # HB1\n  - lb\n",
1312		yaml.Node{
1313			Kind:        yaml.DocumentNode,
1314			Line:        4,
1315			Column:      1,
1316			HeadComment: "# DH1",
1317			Content: []*yaml.Node{{
1318				Kind:   yaml.SequenceNode,
1319				Tag:    "!!seq",
1320				Line:   4,
1321				Column: 1,
1322				Content: []*yaml.Node{{
1323					Kind:        yaml.SequenceNode,
1324					Tag:         "!!seq",
1325					Line:        6,
1326					Column:      3,
1327					HeadComment: "# HL1",
1328					Content: []*yaml.Node{{
1329						Kind:        yaml.ScalarNode,
1330						Tag:         "!!str",
1331						Line:        6,
1332						Column:      5,
1333						Value:       "la",
1334						HeadComment: "# HA1\n",
1335					}, {
1336						Kind:        yaml.ScalarNode,
1337						Tag:         "!!str",
1338						Line:        8,
1339						Column:      5,
1340						Value:       "lb",
1341						HeadComment: "# HB1",
1342					}},
1343				}},
1344			}},
1345		},
1346	}, {
1347		"# DH1\n\n# HA1\nka:\n  # HB1\n  kb:\n    # HC1\n    # HC2\n    - lc # IC\n    # FC1\n    # FC2\n\n    # HD1\n    - ld # ID\n    # FD1\n\n# DF1\n",
1348		yaml.Node{
1349			Kind:        yaml.DocumentNode,
1350			Line:        4,
1351			Column:      1,
1352			HeadComment: "# DH1",
1353			FootComment: "# DF1",
1354			Content: []*yaml.Node{{
1355				Kind:   yaml.MappingNode,
1356				Tag:    "!!map",
1357				Line:   4,
1358				Column: 1,
1359				Content: []*yaml.Node{{
1360					Kind:        yaml.ScalarNode,
1361					Tag:         "!!str",
1362					Line:        4,
1363					Column:      1,
1364					Value:       "ka",
1365					HeadComment: "# HA1",
1366				}, {
1367					Kind:   yaml.MappingNode,
1368					Tag:    "!!map",
1369					Line:   6,
1370					Column: 3,
1371					Content: []*yaml.Node{{
1372						Kind:        yaml.ScalarNode,
1373						Tag:         "!!str",
1374						Line:        6,
1375						Column:      3,
1376						Value:       "kb",
1377						HeadComment: "# HB1",
1378					}, {
1379						Kind:   yaml.SequenceNode,
1380						Line:   9,
1381						Column: 5,
1382						Tag:    "!!seq",
1383						Content: []*yaml.Node{{
1384							Kind:        yaml.ScalarNode,
1385							Tag:         "!!str",
1386							Line:        9,
1387							Column:      7,
1388							Value:       "lc",
1389							HeadComment: "# HC1\n# HC2",
1390							LineComment: "# IC",
1391							FootComment: "# FC1\n# FC2",
1392						}, {
1393							Kind:        yaml.ScalarNode,
1394							Tag:         "!!str",
1395							Line:        14,
1396							Column:      7,
1397							Value:       "ld",
1398							HeadComment: "# HD1",
1399
1400							LineComment: "# ID",
1401							FootComment: "# FD1",
1402						}},
1403					}},
1404				}},
1405			}},
1406		},
1407	}, {
1408		"# DH1\n\n# HA1\nka:\n  # HB1\n  kb:\n    # HC1\n    # HC2\n    - lc # IC\n    # FC1\n    # FC2\n\n    # HD1\n    - ld # ID\n    # FD1\nke: ve\n\n# DF1\n",
1409		yaml.Node{
1410			Kind:        yaml.DocumentNode,
1411			Line:        4,
1412			Column:      1,
1413			HeadComment: "# DH1",
1414			FootComment: "# DF1",
1415			Content: []*yaml.Node{{
1416				Kind:   yaml.MappingNode,
1417				Tag:    "!!map",
1418				Line:   4,
1419				Column: 1,
1420				Content: []*yaml.Node{{
1421					Kind:        yaml.ScalarNode,
1422					Tag:         "!!str",
1423					Line:        4,
1424					Column:      1,
1425					Value:       "ka",
1426					HeadComment: "# HA1",
1427				}, {
1428					Kind:   yaml.MappingNode,
1429					Tag:    "!!map",
1430					Line:   6,
1431					Column: 3,
1432					Content: []*yaml.Node{{
1433						Kind:        yaml.ScalarNode,
1434						Tag:         "!!str",
1435						Line:        6,
1436						Column:      3,
1437						Value:       "kb",
1438						HeadComment: "# HB1",
1439					}, {
1440						Kind:   yaml.SequenceNode,
1441						Line:   9,
1442						Column: 5,
1443						Tag:    "!!seq",
1444						Content: []*yaml.Node{{
1445							Kind:        yaml.ScalarNode,
1446							Tag:         "!!str",
1447							Line:        9,
1448							Column:      7,
1449							Value:       "lc",
1450							HeadComment: "# HC1\n# HC2",
1451							LineComment: "# IC",
1452							FootComment: "# FC1\n# FC2",
1453						}, {
1454							Kind:        yaml.ScalarNode,
1455							Tag:         "!!str",
1456							Line:        14,
1457							Column:      7,
1458							Value:       "ld",
1459							HeadComment: "# HD1",
1460							LineComment: "# ID",
1461							FootComment: "# FD1",
1462						}},
1463					}},
1464				}, {
1465					Kind:   yaml.ScalarNode,
1466					Tag:    "!!str",
1467					Line:   16,
1468					Column: 1,
1469					Value:  "ke",
1470				}, {
1471					Kind:   yaml.ScalarNode,
1472					Tag:    "!!str",
1473					Line:   16,
1474					Column: 5,
1475					Value:  "ve",
1476				}},
1477			}},
1478		},
1479	}, {
1480		"# DH1\n\n# DH2\n\n# HA1\n# HA2\nka:\n  # HB1\n  # HB2\n  kb:\n" +
1481			"    # HC1\n    # HC2\n    kc:\n      # HD1\n      # HD2\n      kd: vd\n      # FD1\n      # FD2\n" +
1482			"    # FC1\n    # FC2\n  # FB1\n  # FB2\n# FA1\n# FA2\n\n# HE1\n# HE2\nke: ve\n# FE1\n# FE2\n\n# DF1\n\n# DF2\n",
1483		yaml.Node{
1484			Kind:        yaml.DocumentNode,
1485			HeadComment: "# DH1\n\n# DH2",
1486			FootComment: "# DF1\n\n# DF2",
1487			Line:        7,
1488			Column:      1,
1489			Content: []*yaml.Node{{
1490				Kind:   yaml.MappingNode,
1491				Tag:    "!!map",
1492				Line:   7,
1493				Column: 1,
1494				Content: []*yaml.Node{{
1495					Kind:        yaml.ScalarNode,
1496					Tag:         "!!str",
1497					Value:       "ka",
1498					HeadComment: "# HA1\n# HA2",
1499					FootComment: "# FA1\n# FA2",
1500					Line:        7,
1501					Column:      1,
1502				}, {
1503					Kind:   yaml.MappingNode,
1504					Tag:    "!!map",
1505					Line:   10,
1506					Column: 3,
1507					Content: []*yaml.Node{{
1508						Kind:        yaml.ScalarNode,
1509						Tag:         "!!str",
1510						Value:       "kb",
1511						HeadComment: "# HB1\n# HB2",
1512						FootComment: "# FB1\n# FB2",
1513						Line:        10,
1514						Column:      3,
1515					}, {
1516						Kind:   yaml.MappingNode,
1517						Tag:    "!!map",
1518						Line:   13,
1519						Column: 5,
1520						Content: []*yaml.Node{{
1521							Kind:        yaml.ScalarNode,
1522							Tag:         "!!str",
1523							Value:       "kc",
1524							HeadComment: "# HC1\n# HC2",
1525							FootComment: "# FC1\n# FC2",
1526							Line:        13,
1527							Column:      5,
1528						}, {
1529							Kind:   yaml.MappingNode,
1530							Tag:    "!!map",
1531							Line:   16,
1532							Column: 7,
1533							Content: []*yaml.Node{{
1534								Kind:        yaml.ScalarNode,
1535								Tag:         "!!str",
1536								Value:       "kd",
1537								HeadComment: "# HD1\n# HD2",
1538								FootComment: "# FD1\n# FD2",
1539								Line:        16,
1540								Column:      7,
1541							}, {
1542								Kind:   yaml.ScalarNode,
1543								Tag:    "!!str",
1544								Value:  "vd",
1545								Line:   16,
1546								Column: 11,
1547							}},
1548						}},
1549					}},
1550				}, {
1551					Kind:        yaml.ScalarNode,
1552					Tag:         "!!str",
1553					Value:       "ke",
1554					HeadComment: "# HE1\n# HE2",
1555					FootComment: "# FE1\n# FE2",
1556					Line:        28,
1557					Column:      1,
1558				}, {
1559					Kind:   yaml.ScalarNode,
1560					Tag:    "!!str",
1561					Value:  "ve",
1562					Line:   28,
1563					Column: 5,
1564				}},
1565			}},
1566		},
1567	}, {
1568		// Same as above but indenting ke in so it's also part of ka's value.
1569		"# DH1\n\n# DH2\n\n# HA1\n# HA2\nka:\n  # HB1\n  # HB2\n  kb:\n" +
1570			"    # HC1\n    # HC2\n    kc:\n      # HD1\n      # HD2\n      kd: vd\n      # FD1\n      # FD2\n" +
1571			"    # FC1\n    # FC2\n  # FB1\n  # FB2\n\n  # HE1\n  # HE2\n  ke: ve\n  # FE1\n  # FE2\n# FA1\n# FA2\n\n# DF1\n\n# DF2\n",
1572		yaml.Node{
1573			Kind:        yaml.DocumentNode,
1574			HeadComment: "# DH1\n\n# DH2",
1575			FootComment: "# DF1\n\n# DF2",
1576			Line:        7,
1577			Column:      1,
1578			Content: []*yaml.Node{{
1579				Kind:   yaml.MappingNode,
1580				Tag:    "!!map",
1581				Line:   7,
1582				Column: 1,
1583				Content: []*yaml.Node{{
1584					Kind:        yaml.ScalarNode,
1585					Tag:         "!!str",
1586					Value:       "ka",
1587					HeadComment: "# HA1\n# HA2",
1588					FootComment: "# FA1\n# FA2",
1589					Line:        7,
1590					Column:      1,
1591				}, {
1592					Kind:   yaml.MappingNode,
1593					Tag:    "!!map",
1594					Line:   10,
1595					Column: 3,
1596					Content: []*yaml.Node{{
1597						Kind:        yaml.ScalarNode,
1598						Tag:         "!!str",
1599						Value:       "kb",
1600						HeadComment: "# HB1\n# HB2",
1601						FootComment: "# FB1\n# FB2",
1602						Line:        10,
1603						Column:      3,
1604					}, {
1605						Kind:   yaml.MappingNode,
1606						Tag:    "!!map",
1607						Line:   13,
1608						Column: 5,
1609						Content: []*yaml.Node{{
1610							Kind:        yaml.ScalarNode,
1611							Tag:         "!!str",
1612							Value:       "kc",
1613							HeadComment: "# HC1\n# HC2",
1614							FootComment: "# FC1\n# FC2",
1615							Line:        13,
1616							Column:      5,
1617						}, {
1618							Kind:   yaml.MappingNode,
1619							Tag:    "!!map",
1620							Line:   16,
1621							Column: 7,
1622							Content: []*yaml.Node{{
1623								Kind:        yaml.ScalarNode,
1624								Tag:         "!!str",
1625								Value:       "kd",
1626								HeadComment: "# HD1\n# HD2",
1627								FootComment: "# FD1\n# FD2",
1628								Line:        16,
1629								Column:      7,
1630							}, {
1631								Kind:   yaml.ScalarNode,
1632								Tag:    "!!str",
1633								Value:  "vd",
1634								Line:   16,
1635								Column: 11,
1636							}},
1637						}},
1638					}, {
1639						Kind:        yaml.ScalarNode,
1640						Tag:         "!!str",
1641						Value:       "ke",
1642						HeadComment: "# HE1\n# HE2",
1643						FootComment: "# FE1\n# FE2",
1644						Line:        26,
1645						Column:      3,
1646					}, {
1647						Kind:   yaml.ScalarNode,
1648						Tag:    "!!str",
1649						Value:  "ve",
1650						Line:   26,
1651						Column: 7,
1652					}},
1653				}},
1654			}},
1655		},
1656	}, {
1657		// Decode only due to lack of newline at the end.
1658		"[decode]# HA1\nka:\n  # HB1\n  kb: vb\n  # FB1\n# FA1",
1659		yaml.Node{
1660			Kind:   yaml.DocumentNode,
1661			Line:   2,
1662			Column: 1,
1663			Content: []*yaml.Node{{
1664				Kind:   yaml.MappingNode,
1665				Tag:    "!!map",
1666				Line:   2,
1667				Column: 1,
1668				Content: []*yaml.Node{{
1669					Kind:        yaml.ScalarNode,
1670					Tag:         "!!str",
1671					Value:       "ka",
1672					HeadComment: "# HA1",
1673					FootComment: "# FA1",
1674					Line:        2,
1675					Column:      1,
1676				}, {
1677					Kind:   yaml.MappingNode,
1678					Tag:    "!!map",
1679					Line:   4,
1680					Column: 3,
1681					Content: []*yaml.Node{{
1682						Kind:        yaml.ScalarNode,
1683						Tag:         "!!str",
1684						Value:       "kb",
1685						HeadComment: "# HB1",
1686						FootComment: "# FB1",
1687						Line:        4,
1688						Column:      3,
1689					}, {
1690						Kind:   yaml.ScalarNode,
1691						Tag:    "!!str",
1692						Value:  "vb",
1693						Line:   4,
1694						Column: 7,
1695					}},
1696				}},
1697			}},
1698		},
1699	}, {
1700		// Same as above, but with newline at the end.
1701		"# HA1\nka:\n  # HB1\n  kb: vb\n  # FB1\n# FA1\n",
1702		yaml.Node{
1703			Kind:   yaml.DocumentNode,
1704			Line:   2,
1705			Column: 1,
1706			Content: []*yaml.Node{{
1707				Kind:   yaml.MappingNode,
1708				Tag:    "!!map",
1709				Line:   2,
1710				Column: 1,
1711				Content: []*yaml.Node{{
1712					Kind:        yaml.ScalarNode,
1713					Tag:         "!!str",
1714					Value:       "ka",
1715					HeadComment: "# HA1",
1716					FootComment: "# FA1",
1717					Line:        2,
1718					Column:      1,
1719				}, {
1720					Kind:   yaml.MappingNode,
1721					Tag:    "!!map",
1722					Line:   4,
1723					Column: 3,
1724					Content: []*yaml.Node{{
1725						Kind:        yaml.ScalarNode,
1726						Tag:         "!!str",
1727						Value:       "kb",
1728						HeadComment: "# HB1",
1729						FootComment: "# FB1",
1730						Line:        4,
1731						Column:      3,
1732					}, {
1733						Kind:   yaml.ScalarNode,
1734						Tag:    "!!str",
1735						Value:  "vb",
1736						Line:   4,
1737						Column: 7,
1738					}},
1739				}},
1740			}},
1741		},
1742	}, {
1743		// Same as above, but without FB1.
1744		"# HA1\nka:\n  # HB1\n  kb: vb\n# FA1\n",
1745		yaml.Node{
1746			Kind:   yaml.DocumentNode,
1747			Line:   2,
1748			Column: 1,
1749			Content: []*yaml.Node{{
1750				Kind:   yaml.MappingNode,
1751				Tag:    "!!map",
1752				Line:   2,
1753				Column: 1,
1754				Content: []*yaml.Node{{
1755					Kind:        yaml.ScalarNode,
1756					Tag:         "!!str",
1757					Value:       "ka",
1758					HeadComment: "# HA1",
1759					FootComment: "# FA1",
1760					Line:        2,
1761					Column:      1,
1762				}, {
1763					Kind:   yaml.MappingNode,
1764					Tag:    "!!map",
1765					Line:   4,
1766					Column: 3,
1767					Content: []*yaml.Node{{
1768						Kind:        yaml.ScalarNode,
1769						Tag:         "!!str",
1770						Value:       "kb",
1771						HeadComment: "# HB1",
1772						Line:        4,
1773						Column:      3,
1774					}, {
1775						Kind:   yaml.ScalarNode,
1776						Tag:    "!!str",
1777						Value:  "vb",
1778						Line:   4,
1779						Column: 7,
1780					}},
1781				}},
1782			}},
1783		},
1784	}, {
1785		// Same as above, but with two newlines at the end. Decode-only for that.
1786		"[decode]# HA1\nka:\n  # HB1\n  kb: vb\n  # FB1\n# FA1\n\n",
1787		yaml.Node{
1788			Kind:   yaml.DocumentNode,
1789			Line:   2,
1790			Column: 1,
1791			Content: []*yaml.Node{{
1792				Kind:   yaml.MappingNode,
1793				Tag:    "!!map",
1794				Line:   2,
1795				Column: 1,
1796				Content: []*yaml.Node{{
1797					Kind:        yaml.ScalarNode,
1798					Tag:         "!!str",
1799					Value:       "ka",
1800					HeadComment: "# HA1",
1801					FootComment: "# FA1",
1802					Line:        2,
1803					Column:      1,
1804				}, {
1805					Kind:   yaml.MappingNode,
1806					Tag:    "!!map",
1807					Line:   4,
1808					Column: 3,
1809					Content: []*yaml.Node{{
1810						Kind:        yaml.ScalarNode,
1811						Tag:         "!!str",
1812						Value:       "kb",
1813						HeadComment: "# HB1",
1814						FootComment: "# FB1",
1815						Line:        4,
1816						Column:      3,
1817					}, {
1818						Kind:   yaml.ScalarNode,
1819						Tag:    "!!str",
1820						Value:  "vb",
1821						Line:   4,
1822						Column: 7,
1823					}},
1824				}},
1825			}},
1826		},
1827	}, {
1828		// Similar to above, but make HB1 look more like a footer of ka.
1829		"[decode]# HA1\nka:\n# HB1\n\n  kb: vb\n# FA1\n",
1830		yaml.Node{
1831			Kind:   yaml.DocumentNode,
1832			Line:   2,
1833			Column: 1,
1834			Content: []*yaml.Node{{
1835				Kind:   yaml.MappingNode,
1836				Tag:    "!!map",
1837				Line:   2,
1838				Column: 1,
1839				Content: []*yaml.Node{{
1840					Kind:        yaml.ScalarNode,
1841					Tag:         "!!str",
1842					Value:       "ka",
1843					HeadComment: "# HA1",
1844					FootComment: "# FA1",
1845					Line:        2,
1846					Column:      1,
1847				}, {
1848					Kind:   yaml.MappingNode,
1849					Tag:    "!!map",
1850					Line:   5,
1851					Column: 3,
1852					Content: []*yaml.Node{{
1853						Kind:        yaml.ScalarNode,
1854						Tag:         "!!str",
1855						Value:       "kb",
1856						HeadComment: "# HB1\n",
1857						Line:        5,
1858						Column:      3,
1859					}, {
1860						Kind:   yaml.ScalarNode,
1861						Tag:    "!!str",
1862						Value:  "vb",
1863						Line:   5,
1864						Column: 7,
1865					}},
1866				}},
1867			}},
1868		},
1869	}, {
1870		"ka:\n  kb: vb\n# FA1\n\nkc: vc\n",
1871		yaml.Node{
1872			Kind:   yaml.DocumentNode,
1873			Line:   1,
1874			Column: 1,
1875			Content: []*yaml.Node{{
1876				Kind:   yaml.MappingNode,
1877				Tag:    "!!map",
1878				Line:   1,
1879				Column: 1,
1880				Content: []*yaml.Node{{
1881					Kind:        yaml.ScalarNode,
1882					Tag:         "!!str",
1883					Value:       "ka",
1884					Line:        1,
1885					Column:      1,
1886					FootComment: "# FA1",
1887				}, {
1888					Kind:   yaml.MappingNode,
1889					Tag:    "!!map",
1890					Line:   2,
1891					Column: 3,
1892					Content: []*yaml.Node{{
1893						Kind:   yaml.ScalarNode,
1894						Tag:    "!!str",
1895						Value:  "kb",
1896						Line:   2,
1897						Column: 3,
1898					}, {
1899						Kind:   yaml.ScalarNode,
1900						Tag:    "!!str",
1901						Value:  "vb",
1902						Line:   2,
1903						Column: 7,
1904					}},
1905				}, {
1906					Kind:   yaml.ScalarNode,
1907					Tag:    "!!str",
1908					Value:  "kc",
1909					Line:   5,
1910					Column: 1,
1911				}, {
1912					Kind:   yaml.ScalarNode,
1913					Tag:    "!!str",
1914					Value:  "vc",
1915					Line:   5,
1916					Column: 5,
1917				}},
1918			}},
1919		},
1920	}, {
1921		"ka:\n  kb: vb\n# HC1\nkc: vc\n",
1922		yaml.Node{
1923			Kind:   yaml.DocumentNode,
1924			Line:   1,
1925			Column: 1,
1926			Content: []*yaml.Node{{
1927				Kind:   yaml.MappingNode,
1928				Tag:    "!!map",
1929				Line:   1,
1930				Column: 1,
1931				Content: []*yaml.Node{{
1932					Kind:   yaml.ScalarNode,
1933					Tag:    "!!str",
1934					Value:  "ka",
1935					Line:   1,
1936					Column: 1,
1937				}, {
1938					Kind:   yaml.MappingNode,
1939					Tag:    "!!map",
1940					Line:   2,
1941					Column: 3,
1942					Content: []*yaml.Node{{
1943						Kind:   yaml.ScalarNode,
1944						Tag:    "!!str",
1945						Value:  "kb",
1946						Line:   2,
1947						Column: 3,
1948					}, {
1949						Kind:   yaml.ScalarNode,
1950						Tag:    "!!str",
1951						Value:  "vb",
1952						Line:   2,
1953						Column: 7,
1954					}},
1955				}, {
1956					Kind:        yaml.ScalarNode,
1957					Tag:         "!!str",
1958					Value:       "kc",
1959					HeadComment: "# HC1",
1960					Line:        4,
1961					Column:      1,
1962				}, {
1963					Kind:   yaml.ScalarNode,
1964					Tag:    "!!str",
1965					Value:  "vc",
1966					Line:   4,
1967					Column: 5,
1968				}},
1969			}},
1970		},
1971	}, {
1972		// Decode only due to empty line before HC1.
1973		"[decode]ka:\n  kb: vb\n\n# HC1\nkc: vc\n",
1974		yaml.Node{
1975			Kind:   yaml.DocumentNode,
1976			Line:   1,
1977			Column: 1,
1978			Content: []*yaml.Node{{
1979				Kind:   yaml.MappingNode,
1980				Tag:    "!!map",
1981				Line:   1,
1982				Column: 1,
1983				Content: []*yaml.Node{{
1984					Kind:   yaml.ScalarNode,
1985					Tag:    "!!str",
1986					Value:  "ka",
1987					Line:   1,
1988					Column: 1,
1989				}, {
1990					Kind:   yaml.MappingNode,
1991					Tag:    "!!map",
1992					Line:   2,
1993					Column: 3,
1994					Content: []*yaml.Node{{
1995						Kind:   yaml.ScalarNode,
1996						Tag:    "!!str",
1997						Value:  "kb",
1998						Line:   2,
1999						Column: 3,
2000					}, {
2001						Kind:   yaml.ScalarNode,
2002						Tag:    "!!str",
2003						Value:  "vb",
2004						Line:   2,
2005						Column: 7,
2006					}},
2007				}, {
2008					Kind:        yaml.ScalarNode,
2009					Tag:         "!!str",
2010					Value:       "kc",
2011					HeadComment: "# HC1",
2012					Line:        5,
2013					Column:      1,
2014				}, {
2015					Kind:   yaml.ScalarNode,
2016					Tag:    "!!str",
2017					Value:  "vc",
2018					Line:   5,
2019					Column: 5,
2020				}},
2021			}},
2022		},
2023	}, {
2024		// Decode-only due to empty lines around HC1.
2025		"[decode]ka:\n  kb: vb\n\n# HC1\n\nkc: vc\n",
2026		yaml.Node{
2027			Kind:   yaml.DocumentNode,
2028			Line:   1,
2029			Column: 1,
2030			Content: []*yaml.Node{{
2031				Kind:   yaml.MappingNode,
2032				Tag:    "!!map",
2033				Line:   1,
2034				Column: 1,
2035				Content: []*yaml.Node{{
2036					Kind:   yaml.ScalarNode,
2037					Tag:    "!!str",
2038					Value:  "ka",
2039					Line:   1,
2040					Column: 1,
2041				}, {
2042					Kind:   yaml.MappingNode,
2043					Tag:    "!!map",
2044					Line:   2,
2045					Column: 3,
2046					Content: []*yaml.Node{{
2047						Kind:   yaml.ScalarNode,
2048						Tag:    "!!str",
2049						Value:  "kb",
2050						Line:   2,
2051						Column: 3,
2052					}, {
2053						Kind:   yaml.ScalarNode,
2054						Tag:    "!!str",
2055						Value:  "vb",
2056						Line:   2,
2057						Column: 7,
2058					}},
2059				}, {
2060					Kind:        yaml.ScalarNode,
2061					Tag:         "!!str",
2062					Value:       "kc",
2063					HeadComment: "# HC1\n",
2064					Line:        6,
2065					Column:      1,
2066				}, {
2067					Kind:   yaml.ScalarNode,
2068					Tag:    "!!str",
2069					Value:  "vc",
2070					Line:   6,
2071					Column: 5,
2072				}},
2073			}},
2074		},
2075	}, {
2076		"ka: # IA\n  kb: # IB\n",
2077		yaml.Node{
2078			Kind:   yaml.DocumentNode,
2079			Line:   1,
2080			Column: 1,
2081			Content: []*yaml.Node{{
2082				Kind:   yaml.MappingNode,
2083				Tag:    "!!map",
2084				Line:   1,
2085				Column: 1,
2086				Content: []*yaml.Node{{
2087					Kind:        yaml.ScalarNode,
2088					Tag:         "!!str",
2089					Value:       "ka",
2090					Line:        1,
2091					Column:      1,
2092					LineComment: "# IA",
2093				}, {
2094					Kind:   yaml.MappingNode,
2095					Tag:    "!!map",
2096					Line:   2,
2097					Column: 3,
2098					Content: []*yaml.Node{{
2099						Kind:        yaml.ScalarNode,
2100						Tag:         "!!str",
2101						Value:       "kb",
2102						Line:        2,
2103						Column:      3,
2104						LineComment: "# IB",
2105					}, {
2106						Kind:   yaml.ScalarNode,
2107						Tag:    "!!null",
2108						Line:   2,
2109						Column: 6,
2110					}},
2111				}},
2112			}},
2113		},
2114	}, {
2115		"# HA1\nka:\n  # HB1\n  kb: vb\n  # FB1\n# HC1\n# HC2\nkc: vc\n# FC1\n# FC2\n",
2116		yaml.Node{
2117			Kind:   yaml.DocumentNode,
2118			Line:   2,
2119			Column: 1,
2120			Content: []*yaml.Node{{
2121				Kind:   yaml.MappingNode,
2122				Tag:    "!!map",
2123				Line:   2,
2124				Column: 1,
2125				Content: []*yaml.Node{{
2126					Kind:        yaml.ScalarNode,
2127					Tag:         "!!str",
2128					Value:       "ka",
2129					HeadComment: "# HA1",
2130					Line:        2,
2131					Column:      1,
2132				}, {
2133					Kind:   yaml.MappingNode,
2134					Tag:    "!!map",
2135					Line:   4,
2136					Column: 3,
2137					Content: []*yaml.Node{{
2138						Kind:        yaml.ScalarNode,
2139						Tag:         "!!str",
2140						Value:       "kb",
2141						HeadComment: "# HB1",
2142						FootComment: "# FB1",
2143						Line:        4,
2144						Column:      3,
2145					}, {
2146						Kind:   yaml.ScalarNode,
2147						Tag:    "!!str",
2148						Value:  "vb",
2149						Line:   4,
2150						Column: 7,
2151					}},
2152				}, {
2153					Kind:        yaml.ScalarNode,
2154					Tag:         "!!str",
2155					Value:       "kc",
2156					HeadComment: "# HC1\n# HC2",
2157					FootComment: "# FC1\n# FC2",
2158					Line:        8,
2159					Column:      1,
2160				}, {
2161					Kind:   yaml.ScalarNode,
2162					Tag:    "!!str",
2163					Value:  "vc",
2164					Line:   8,
2165					Column: 5,
2166				}},
2167			}},
2168		},
2169	}, {
2170		// Same as above, but decode only due to empty line between ka's value and kc's headers.
2171		"[decode]# HA1\nka:\n  # HB1\n  kb: vb\n  # FB1\n\n# HC1\n# HC2\nkc: vc\n# FC1\n# FC2\n",
2172		yaml.Node{
2173			Kind:   yaml.DocumentNode,
2174			Line:   2,
2175			Column: 1,
2176			Content: []*yaml.Node{{
2177				Kind:   yaml.MappingNode,
2178				Tag:    "!!map",
2179				Line:   2,
2180				Column: 1,
2181				Content: []*yaml.Node{{
2182					Kind:        yaml.ScalarNode,
2183					Tag:         "!!str",
2184					Value:       "ka",
2185					HeadComment: "# HA1",
2186					Line:        2,
2187					Column:      1,
2188				}, {
2189					Kind:   yaml.MappingNode,
2190					Tag:    "!!map",
2191					Line:   4,
2192					Column: 3,
2193					Content: []*yaml.Node{{
2194						Kind:        yaml.ScalarNode,
2195						Tag:         "!!str",
2196						Value:       "kb",
2197						HeadComment: "# HB1",
2198						FootComment: "# FB1",
2199						Line:        4,
2200						Column:      3,
2201					}, {
2202						Kind:   yaml.ScalarNode,
2203						Tag:    "!!str",
2204						Value:  "vb",
2205						Line:   4,
2206						Column: 7,
2207					}},
2208				}, {
2209					Kind:        yaml.ScalarNode,
2210					Tag:         "!!str",
2211					Value:       "kc",
2212					HeadComment: "# HC1\n# HC2",
2213					FootComment: "# FC1\n# FC2",
2214					Line:        9,
2215					Column:      1,
2216				}, {
2217					Kind:   yaml.ScalarNode,
2218					Tag:    "!!str",
2219					Value:  "vc",
2220					Line:   9,
2221					Column: 5,
2222				}},
2223			}},
2224		},
2225	}, {
2226		"# H1\n[la, lb] # I\n# F1\n",
2227		yaml.Node{
2228			Kind:   yaml.DocumentNode,
2229			Line:   2,
2230			Column: 1,
2231			Content: []*yaml.Node{{
2232				Kind:        yaml.SequenceNode,
2233				Tag:         "!!seq",
2234				Style:       yaml.FlowStyle,
2235				Line:        2,
2236				Column:      1,
2237				HeadComment: "# H1",
2238				LineComment: "# I",
2239				FootComment: "# F1",
2240				Content: []*yaml.Node{{
2241					Kind:   yaml.ScalarNode,
2242					Tag:    "!!str",
2243					Line:   2,
2244					Column: 2,
2245					Value:  "la",
2246				}, {
2247					Kind:   yaml.ScalarNode,
2248					Tag:    "!!str",
2249					Line:   2,
2250					Column: 6,
2251					Value:  "lb",
2252				}},
2253			}},
2254		},
2255	}, {
2256		"# DH1\n\n# SH1\n[\n  # HA1\n  la, # IA\n  # FA1\n\n  # HB1\n  lb, # IB\n  # FB1\n]\n# SF1\n\n# DF1\n",
2257		yaml.Node{
2258			Kind:        yaml.DocumentNode,
2259			Line:        4,
2260			Column:      1,
2261			HeadComment: "# DH1",
2262			FootComment: "# DF1",
2263			Content: []*yaml.Node{{
2264				Kind:        yaml.SequenceNode,
2265				Tag:         "!!seq",
2266				Style:       yaml.FlowStyle,
2267				Line:        4,
2268				Column:      1,
2269				HeadComment: "# SH1",
2270				FootComment: "# SF1",
2271				Content: []*yaml.Node{{
2272					Kind:        yaml.ScalarNode,
2273					Tag:         "!!str",
2274					Line:        6,
2275					Column:      3,
2276					Value:       "la",
2277					HeadComment: "# HA1",
2278					LineComment: "# IA",
2279					FootComment: "# FA1",
2280				}, {
2281					Kind:        yaml.ScalarNode,
2282					Tag:         "!!str",
2283					Line:        10,
2284					Column:      3,
2285					Value:       "lb",
2286					HeadComment: "# HB1",
2287					LineComment: "# IB",
2288					FootComment: "# FB1",
2289				}},
2290			}},
2291		},
2292	}, {
2293		// Same as above, but with extra newlines before FB1 and FB2
2294		"[decode]# DH1\n\n# SH1\n[\n  # HA1\n  la, # IA\n  # FA1\n\n  # HB1\n  lb, # IB\n\n\n  # FB1\n\n# FB2\n]\n# SF1\n\n# DF1\n",
2295		yaml.Node{
2296			Kind:        yaml.DocumentNode,
2297			Line:        4,
2298			Column:      1,
2299			HeadComment: "# DH1",
2300			FootComment: "# DF1",
2301			Content: []*yaml.Node{{
2302				Kind:        yaml.SequenceNode,
2303				Tag:         "!!seq",
2304				Style:       yaml.FlowStyle,
2305				Line:        4,
2306				Column:      1,
2307				HeadComment: "# SH1",
2308				FootComment: "# SF1",
2309				Content: []*yaml.Node{{
2310					Kind:        yaml.ScalarNode,
2311					Tag:         "!!str",
2312					Line:        6,
2313					Column:      3,
2314					Value:       "la",
2315					HeadComment: "# HA1",
2316					LineComment: "# IA",
2317					FootComment: "# FA1",
2318				}, {
2319					Kind:        yaml.ScalarNode,
2320					Tag:         "!!str",
2321					Line:        10,
2322					Column:      3,
2323					Value:       "lb",
2324					HeadComment: "# HB1",
2325					LineComment: "# IB",
2326					FootComment: "# FB1\n\n# FB2",
2327				}},
2328			}},
2329		},
2330	}, {
2331		"# DH1\n\n# SH1\n[\n  # HA1\n  la,\n  # FA1\n\n  # HB1\n  lb,\n  # FB1\n]\n# SF1\n\n# DF1\n",
2332		yaml.Node{
2333			Kind:        yaml.DocumentNode,
2334			Line:        4,
2335			Column:      1,
2336			HeadComment: "# DH1",
2337			FootComment: "# DF1",
2338			Content: []*yaml.Node{{
2339				Kind:        yaml.SequenceNode,
2340				Tag:         "!!seq",
2341				Style:       yaml.FlowStyle,
2342				Line:        4,
2343				Column:      1,
2344				HeadComment: "# SH1",
2345				FootComment: "# SF1",
2346				Content: []*yaml.Node{{
2347					Kind:        yaml.ScalarNode,
2348					Tag:         "!!str",
2349					Line:        6,
2350					Column:      3,
2351					Value:       "la",
2352					HeadComment: "# HA1",
2353					FootComment: "# FA1",
2354				}, {
2355					Kind:        yaml.ScalarNode,
2356					Tag:         "!!str",
2357					Line:        10,
2358					Column:      3,
2359					Value:       "lb",
2360					HeadComment: "# HB1",
2361					FootComment: "# FB1",
2362				}},
2363			}},
2364		},
2365	}, {
2366		"ka:\n  kb: [\n    # HA1\n    la,\n    # FA1\n\n    # HB1\n    lb,\n    # FB1\n  ]\n",
2367		yaml.Node{
2368			Kind:   yaml.DocumentNode,
2369			Line:   1,
2370			Column: 1,
2371			Content: []*yaml.Node{{
2372				Kind:   yaml.MappingNode,
2373				Tag:    "!!map",
2374				Line:   1,
2375				Column: 1,
2376				Content: []*yaml.Node{{
2377					Kind:   yaml.ScalarNode,
2378					Tag:    "!!str",
2379					Value:  "ka",
2380					Line:   1,
2381					Column: 1,
2382				}, {
2383					Kind:   0x4,
2384					Tag:    "!!map",
2385					Line:   2,
2386					Column: 3,
2387					Content: []*yaml.Node{{
2388						Kind:   yaml.ScalarNode,
2389						Tag:    "!!str",
2390						Value:  "kb",
2391						Line:   2,
2392						Column: 3,
2393					}, {
2394						Kind:   yaml.SequenceNode,
2395						Style:  0x20,
2396						Tag:    "!!seq",
2397						Line:   2,
2398						Column: 7,
2399						Content: []*yaml.Node{{
2400							Kind:        yaml.ScalarNode,
2401							Tag:         "!!str",
2402							Value:       "la",
2403							HeadComment: "# HA1",
2404							FootComment: "# FA1",
2405							Line:        4,
2406							Column:      5,
2407						}, {
2408							Kind:        yaml.ScalarNode,
2409							Tag:         "!!str",
2410							Value:       "lb",
2411							HeadComment: "# HB1",
2412							FootComment: "# FB1",
2413							Line:        8,
2414							Column:      5,
2415						}},
2416					}},
2417				}},
2418			}},
2419		},
2420	}, {
2421		"# DH1\n\n# MH1\n{\n  # HA1\n  ka: va, # IA\n  # FA1\n\n  # HB1\n  kb: vb, # IB\n  # FB1\n}\n# MF1\n\n# DF1\n",
2422		yaml.Node{
2423			Kind:        yaml.DocumentNode,
2424			Line:        4,
2425			Column:      1,
2426			HeadComment: "# DH1",
2427			FootComment: "# DF1",
2428			Content: []*yaml.Node{{
2429				Kind:        yaml.MappingNode,
2430				Tag:         "!!map",
2431				Style:       yaml.FlowStyle,
2432				Line:        4,
2433				Column:      1,
2434				HeadComment: "# MH1",
2435				FootComment: "# MF1",
2436				Content: []*yaml.Node{{
2437					Kind:        yaml.ScalarNode,
2438					Tag:         "!!str",
2439					Line:        6,
2440					Column:      3,
2441					Value:       "ka",
2442					HeadComment: "# HA1",
2443					FootComment: "# FA1",
2444				}, {
2445					Kind:        yaml.ScalarNode,
2446					Tag:         "!!str",
2447					Line:        6,
2448					Column:      7,
2449					Value:       "va",
2450					LineComment: "# IA",
2451				}, {
2452					Kind:        yaml.ScalarNode,
2453					Tag:         "!!str",
2454					Line:        10,
2455					Column:      3,
2456					Value:       "kb",
2457					HeadComment: "# HB1",
2458					FootComment: "# FB1",
2459				}, {
2460					Kind:        yaml.ScalarNode,
2461					Tag:         "!!str",
2462					Line:        10,
2463					Column:      7,
2464					Value:       "vb",
2465					LineComment: "# IB",
2466				}},
2467			}},
2468		},
2469	}, {
2470		"# DH1\n\n# MH1\n{\n  # HA1\n  ka: va,\n  # FA1\n\n  # HB1\n  kb: vb,\n  # FB1\n}\n# MF1\n\n# DF1\n",
2471		yaml.Node{
2472			Kind:        yaml.DocumentNode,
2473			Line:        4,
2474			Column:      1,
2475			HeadComment: "# DH1",
2476			FootComment: "# DF1",
2477			Content: []*yaml.Node{{
2478				Kind:        yaml.MappingNode,
2479				Tag:         "!!map",
2480				Style:       yaml.FlowStyle,
2481				Line:        4,
2482				Column:      1,
2483				HeadComment: "# MH1",
2484				FootComment: "# MF1",
2485				Content: []*yaml.Node{{
2486					Kind:        yaml.ScalarNode,
2487					Tag:         "!!str",
2488					Line:        6,
2489					Column:      3,
2490					Value:       "ka",
2491					HeadComment: "# HA1",
2492					FootComment: "# FA1",
2493				}, {
2494					Kind:   yaml.ScalarNode,
2495					Tag:    "!!str",
2496					Line:   6,
2497					Column: 7,
2498					Value:  "va",
2499				}, {
2500					Kind:        yaml.ScalarNode,
2501					Tag:         "!!str",
2502					Line:        10,
2503					Column:      3,
2504					Value:       "kb",
2505					HeadComment: "# HB1",
2506					FootComment: "# FB1",
2507				}, {
2508					Kind:   yaml.ScalarNode,
2509					Tag:    "!!str",
2510					Line:   10,
2511					Column: 7,
2512					Value:  "vb",
2513				}},
2514			}},
2515		},
2516	}, {
2517		"# DH1\n\n# DH2\n\n# HA1\n# HA2\n- &x la # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\n- *x # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n",
2518		yaml.Node{
2519			Kind:        yaml.DocumentNode,
2520			Line:        7,
2521			Column:      1,
2522			HeadComment: "# DH1\n\n# DH2",
2523			FootComment: "# DF1\n\n# DF2",
2524			Content: []*yaml.Node{{
2525				Kind:   yaml.SequenceNode,
2526				Tag:    "!!seq",
2527				Line:   7,
2528				Column: 1,
2529				Content: []*yaml.Node{
2530					saveNode("x", &yaml.Node{
2531						Kind:        yaml.ScalarNode,
2532						Tag:         "!!str",
2533						Line:        7,
2534						Column:      3,
2535						Value:       "la",
2536						HeadComment: "# HA1\n# HA2",
2537						LineComment: "# IA",
2538						FootComment: "# FA1\n# FA2",
2539						Anchor:      "x",
2540					}), {
2541						Kind:        yaml.AliasNode,
2542						Line:        13,
2543						Column:      3,
2544						Value:       "x",
2545						Alias:       dropNode("x"),
2546						HeadComment: "# HB1\n# HB2",
2547						LineComment: "# IB",
2548						FootComment: "# FB1\n# FB2",
2549					},
2550				},
2551			}},
2552		},
2553	},
2554}
2555
2556func (s *S) TestNodeRoundtrip(c *C) {
2557	defer os.Setenv("TZ", os.Getenv("TZ"))
2558	os.Setenv("TZ", "UTC")
2559	for i, item := range nodeTests {
2560		c.Logf("test %d: %q", i, item.yaml)
2561
2562		if strings.Contains(item.yaml, "#") {
2563			var buf bytes.Buffer
2564			fprintComments(&buf, &item.node, "    ")
2565			c.Logf("  expected comments:\n%s", buf.Bytes())
2566		}
2567
2568		decode := true
2569		encode := true
2570
2571		testYaml := item.yaml
2572		if s := strings.TrimPrefix(testYaml, "[decode]"); s != testYaml {
2573			encode = false
2574			testYaml = s
2575		}
2576		if s := strings.TrimPrefix(testYaml, "[encode]"); s != testYaml {
2577			decode = false
2578			testYaml = s
2579		}
2580
2581		if decode {
2582			var node yaml.Node
2583			err := yaml.Unmarshal([]byte(testYaml), &node)
2584			c.Assert(err, IsNil)
2585			if strings.Contains(item.yaml, "#") {
2586				var buf bytes.Buffer
2587				fprintComments(&buf, &node, "    ")
2588				c.Logf("  obtained comments:\n%s", buf.Bytes())
2589			}
2590			c.Assert(&node, DeepEquals, &item.node)
2591		}
2592		if encode {
2593			node := deepCopyNode(&item.node, nil)
2594			buf := bytes.Buffer{}
2595			enc := yaml.NewEncoder(&buf)
2596			enc.SetIndent(2)
2597			err := enc.Encode(node)
2598			c.Assert(err, IsNil)
2599			err = enc.Close()
2600			c.Assert(err, IsNil)
2601			c.Assert(buf.String(), Equals, testYaml)
2602
2603			// Ensure there were no mutations to the tree.
2604			c.Assert(node, DeepEquals, &item.node)
2605		}
2606	}
2607}
2608
2609func deepCopyNode(node *yaml.Node, cache map[*yaml.Node]*yaml.Node) *yaml.Node {
2610	if n, ok := cache[node]; ok {
2611		return n
2612	}
2613	if cache == nil {
2614		cache = make(map[*yaml.Node]*yaml.Node)
2615	}
2616	copy := *node
2617	cache[node] = &copy
2618	copy.Content = nil
2619	for _, elem := range node.Content {
2620		copy.Content = append(copy.Content, deepCopyNode(elem, cache))
2621	}
2622	if node.Alias != nil {
2623		copy.Alias = deepCopyNode(node.Alias, cache)
2624	}
2625	return &copy
2626}
2627
2628var savedNodes = make(map[string]*yaml.Node)
2629
2630func saveNode(name string, node *yaml.Node) *yaml.Node {
2631	savedNodes[name] = node
2632	return node
2633}
2634
2635func peekNode(name string) *yaml.Node {
2636	return savedNodes[name]
2637}
2638
2639func dropNode(name string) *yaml.Node {
2640	node := savedNodes[name]
2641	delete(savedNodes, name)
2642	return node
2643}
2644
2645var setStringTests = []struct {
2646	str  string
2647	yaml string
2648	node yaml.Node
2649}{
2650	{
2651		"something simple",
2652		"something simple\n",
2653		yaml.Node{
2654			Kind:  yaml.ScalarNode,
2655			Value: "something simple",
2656			Tag:   "!!str",
2657		},
2658	}, {
2659		`"quoted value"`,
2660		"'\"quoted value\"'\n",
2661		yaml.Node{
2662			Kind:  yaml.ScalarNode,
2663			Value: `"quoted value"`,
2664			Tag:   "!!str",
2665		},
2666	}, {
2667		"multi\nline",
2668		"|-\n  multi\n  line\n",
2669		yaml.Node{
2670			Kind:  yaml.ScalarNode,
2671			Value: "multi\nline",
2672			Tag:   "!!str",
2673			Style: yaml.LiteralStyle,
2674		},
2675	}, {
2676		"123",
2677		"\"123\"\n",
2678		yaml.Node{
2679			Kind:  yaml.ScalarNode,
2680			Value: "123",
2681			Tag:   "!!str",
2682		},
2683	}, {
2684		"multi\nline\n",
2685		"|\n  multi\n  line\n",
2686		yaml.Node{
2687			Kind:  yaml.ScalarNode,
2688			Value: "multi\nline\n",
2689			Tag:   "!!str",
2690			Style: yaml.LiteralStyle,
2691		},
2692	}, {
2693		"\x80\x81\x82",
2694		"!!binary gIGC\n",
2695		yaml.Node{
2696			Kind:  yaml.ScalarNode,
2697			Value: "gIGC",
2698			Tag:   "!!binary",
2699		},
2700	},
2701}
2702
2703func (s *S) TestSetString(c *C) {
2704	defer os.Setenv("TZ", os.Getenv("TZ"))
2705	os.Setenv("TZ", "UTC")
2706	for i, item := range setStringTests {
2707		c.Logf("test %d: %q", i, item.str)
2708
2709		var node yaml.Node
2710
2711		node.SetString(item.str)
2712
2713		c.Assert(node, DeepEquals, item.node)
2714
2715		buf := bytes.Buffer{}
2716		enc := yaml.NewEncoder(&buf)
2717		enc.SetIndent(2)
2718		err := enc.Encode(&item.node)
2719		c.Assert(err, IsNil)
2720		err = enc.Close()
2721		c.Assert(err, IsNil)
2722		c.Assert(buf.String(), Equals, item.yaml)
2723
2724		var doc yaml.Node
2725		err = yaml.Unmarshal([]byte(item.yaml), &doc)
2726		c.Assert(err, IsNil)
2727
2728		var str string
2729		err = node.Decode(&str)
2730		c.Assert(err, IsNil)
2731		c.Assert(str, Equals, item.str)
2732	}
2733}
2734
2735var nodeEncodeDecodeTests = []struct {
2736	value interface{}
2737	yaml  string
2738	node  yaml.Node
2739}{{
2740	"something simple",
2741	"something simple\n",
2742	yaml.Node{
2743		Kind:  yaml.ScalarNode,
2744		Value: "something simple",
2745		Tag:   "!!str",
2746	},
2747}, {
2748	`"quoted value"`,
2749	"'\"quoted value\"'\n",
2750	yaml.Node{
2751		Kind:  yaml.ScalarNode,
2752		Style: yaml.SingleQuotedStyle,
2753		Value: `"quoted value"`,
2754		Tag:   "!!str",
2755	},
2756}, {
2757	123,
2758	"123",
2759	yaml.Node{
2760		Kind:  yaml.ScalarNode,
2761		Value: `123`,
2762		Tag:   "!!int",
2763	},
2764}, {
2765	[]interface{}{1, 2},
2766	"[1, 2]",
2767	yaml.Node{
2768		Kind: yaml.SequenceNode,
2769		Tag:  "!!seq",
2770		Content: []*yaml.Node{{
2771			Kind:  yaml.ScalarNode,
2772			Value: "1",
2773			Tag:   "!!int",
2774		}, {
2775			Kind:  yaml.ScalarNode,
2776			Value: "2",
2777			Tag:   "!!int",
2778		}},
2779	},
2780}, {
2781	map[string]interface{}{"a": "b"},
2782	"a: b",
2783	yaml.Node{
2784		Kind: yaml.MappingNode,
2785		Tag:  "!!map",
2786		Content: []*yaml.Node{{
2787			Kind:  yaml.ScalarNode,
2788			Value: "a",
2789			Tag:   "!!str",
2790		}, {
2791			Kind:  yaml.ScalarNode,
2792			Value: "b",
2793			Tag:   "!!str",
2794		}},
2795	},
2796}}
2797
2798func (s *S) TestNodeEncodeDecode(c *C) {
2799	for i, item := range nodeEncodeDecodeTests {
2800		c.Logf("Encode/Decode test value #%d: %#v", i, item.value)
2801
2802		var v interface{}
2803		err := item.node.Decode(&v)
2804		c.Assert(err, IsNil)
2805		c.Assert(v, DeepEquals, item.value)
2806
2807		var n yaml.Node
2808		err = n.Encode(item.value)
2809		c.Assert(err, IsNil)
2810		c.Assert(n, DeepEquals, item.node)
2811	}
2812}
2813
2814func (s *S) TestNodeZeroEncodeDecode(c *C) {
2815	// Zero node value behaves as nil when encoding...
2816	var n yaml.Node
2817	data, err := yaml.Marshal(&n)
2818	c.Assert(err, IsNil)
2819	c.Assert(string(data), Equals, "null\n")
2820
2821	// ... and decoding.
2822	var v *struct{} = &struct{}{}
2823	c.Assert(n.Decode(&v), IsNil)
2824	c.Assert(v, IsNil)
2825
2826	// ... and even when looking for its tag.
2827	c.Assert(n.ShortTag(), Equals, "!!null")
2828
2829	// Kind zero is still unknown, though.
2830	n.Line = 1
2831	_, err = yaml.Marshal(&n)
2832	c.Assert(err, ErrorMatches, "yaml: cannot encode node with unknown kind 0")
2833	c.Assert(n.Decode(&v), ErrorMatches, "yaml: cannot decode node with unknown kind 0")
2834}
2835
2836func (s *S) TestNodeOmitEmpty(c *C) {
2837	var v struct {
2838		A int
2839		B yaml.Node ",omitempty"
2840	}
2841	v.A = 1
2842	data, err := yaml.Marshal(&v)
2843	c.Assert(err, IsNil)
2844	c.Assert(string(data), Equals, "a: 1\n")
2845
2846	v.B.Line = 1
2847	_, err = yaml.Marshal(&v)
2848	c.Assert(err, ErrorMatches, "yaml: cannot encode node with unknown kind 0")
2849}
2850
2851func fprintComments(out io.Writer, node *yaml.Node, indent string) {
2852	switch node.Kind {
2853	case yaml.ScalarNode:
2854		fmt.Fprintf(out, "%s<%s> ", indent, node.Value)
2855		fprintCommentSet(out, node)
2856		fmt.Fprintf(out, "\n")
2857	case yaml.DocumentNode:
2858		fmt.Fprintf(out, "%s<DOC> ", indent)
2859		fprintCommentSet(out, node)
2860		fmt.Fprintf(out, "\n")
2861		for i := 0; i < len(node.Content); i++ {
2862			fprintComments(out, node.Content[i], indent+"  ")
2863		}
2864	case yaml.MappingNode:
2865		fmt.Fprintf(out, "%s<MAP> ", indent)
2866		fprintCommentSet(out, node)
2867		fmt.Fprintf(out, "\n")
2868		for i := 0; i < len(node.Content); i += 2 {
2869			fprintComments(out, node.Content[i], indent+"  ")
2870			fprintComments(out, node.Content[i+1], indent+"  ")
2871		}
2872	case yaml.SequenceNode:
2873		fmt.Fprintf(out, "%s<SEQ> ", indent)
2874		fprintCommentSet(out, node)
2875		fmt.Fprintf(out, "\n")
2876		for i := 0; i < len(node.Content); i++ {
2877			fprintComments(out, node.Content[i], indent+"  ")
2878		}
2879	}
2880}
2881
2882func fprintCommentSet(out io.Writer, node *yaml.Node) {
2883	if len(node.HeadComment)+len(node.LineComment)+len(node.FootComment) > 0 {
2884		fmt.Fprintf(out, "%q / %q / %q", node.HeadComment, node.LineComment, node.FootComment)
2885	}
2886}
2887