go-yaml/parser/parser_test.go

644 lines
6.9 KiB
Go
Raw Normal View History

2019-10-16 18:21:20 +09:00
package parser_test
import (
"fmt"
2019-12-22 11:50:07 +09:00
"path/filepath"
2019-10-16 18:21:20 +09:00
"strings"
"testing"
"github.com/goccy/go-yaml/ast"
"github.com/goccy/go-yaml/lexer"
"github.com/goccy/go-yaml/parser"
"github.com/goccy/go-yaml/printer"
)
func TestParser(t *testing.T) {
sources := []string{
"null\n",
"{}\n",
"v: hi\n",
"v: \"true\"\n",
"v: \"false\"\n",
"v: true\n",
"v: false\n",
"v: 10\n",
"v: -10\n",
"v: 42\n",
"v: 4294967296\n",
"v: \"10\"\n",
"v: 0.1\n",
"v: 0.99\n",
"v: -0.1\n",
"v: .inf\n",
"v: -.inf\n",
"v: .nan\n",
"v: null\n",
"v: \"\"\n",
"v:\n- A\n- B\n",
"a: '-'\n",
"123\n",
"hello: world\n",
"a: null\n",
"v:\n- A\n- 1\n- B:\n - 2\n - 3\n",
"a:\n b: c\n",
"a: {x: 1}\n",
"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
"a: [1, 2]\n",
"a: {b: c, d: e}\n",
"a: 3s\n",
"a: <foo>\n",
"a: \"1:1\"\n",
"a: 1.2.3.4\n",
"a: \"2015-02-24T18:19:39Z\"\n",
"a: 'b: c'\n",
"a: 'Hello #comment'\n",
"a: 100.5\n",
"a: bogus\n",
"a: \"\\0\"\n",
"b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n",
" a : b \n",
"a: b # comment\nb: c\n",
"---\na: b\n",
"a: b\n...\n",
"%YAML 1.2\n---\n",
"a: !!binary gIGC\n",
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
"- !tag\n a: b\n c: d\n",
"v:\n- A\n- |-\n B\n C\n",
"v:\n- A\n- >-\n B\n C\n",
"v: |-\n 0\n",
"v: |-\n 0\nx: 0",
`"a\n1\nb"`,
2019-10-16 18:21:20 +09:00
}
for _, src := range sources {
fmt.Printf(src)
2019-10-21 12:53:30 +09:00
tokens := lexer.Tokenize(src)
2019-10-16 18:21:20 +09:00
var printer printer.Printer
fmt.Println(printer.PrintTokens(tokens))
2019-11-05 17:02:55 +09:00
ast, err := parser.Parse(tokens, 0)
2019-10-16 18:21:20 +09:00
if err != nil {
t.Fatalf("%+v", err)
}
fmt.Printf("%+v\n", ast)
}
}
func TestParseComplicatedDocument(t *testing.T) {
tests := []struct {
source string
expect string
}{
{
`
american:
- Boston Red Sox
- Detroit Tigers
- New York Yankees
national:
- New York Mets
- Chicago Cubs
- Atlanta Braves
`, `
american:
- Boston Red Sox
- Detroit Tigers
- New York Yankees
national:
- New York Mets
- Chicago Cubs
- Atlanta Braves
`,
},
{
`
a:
b: c
d: e
f: g
h:
i: j
k:
l: m
n: o
p: q
r: s
`, `
a:
b: c
d: e
f: g
h:
i: j
k:
l: m
n: o
p: q
r: s
`,
},
{
`
- a:
- b
- c
- d
`, `
- a:
- b
- c
- d
`,
},
{
`
- a
- b
- c
- d
- e
- f
`, `
- a
- b
- c - d - e
- f
`,
},
{
`
a: 0 - 1
`,
`
a: 0 - 1
2019-10-16 18:21:20 +09:00
`,
},
{`
- a:
b: c
d: e
- f:
g: h
`,
`
- a:
b: c
d: e
- f:
g: h
`,
},
{
`
a:
b
c
d: e
`, `
a: b c
d: e
`,
},
{
`
a
b
c
`, `
a b c
`,
},
{
`
a:
- b
- c
`, `
a:
- b
- c
`,
},
{
`
- a :
b: c
`, `
- a:
b: c
`,
},
{
`
- a:
b
c
d
hoge: fuga
`, `
- a: b c d
hoge: fuga
`,
},
{
`
- a # ' " # - : %
- b # " # - : % '
- c # # - : % ' "
- d # - : % ' " #
- e # : % ' " # -
- f # % ' : # - :
`,
`
- a
- b
- c
- d
- e
- f
`,
},
{
`
# comment
a: # comment
# comment
b: c # comment
# comment
d: e # comment
# comment
`,
`
a:
b: c
d: e
`,
},
{
`
a: b#notcomment
`,
`
a: b#notcomment
2019-10-16 18:21:20 +09:00
`,
},
{
`
anchored: &anchor foo
aliased: *anchor
`,
`
anchored: &anchor foo
aliased: *anchor
`,
},
{
`
---
- &CENTER { x: 1, y: 2 }
- &LEFT { x: 0, y: 2 }
- &BIG { r: 10 }
- &SMALL { r: 1 }
# All the following maps are equal:
- # Explicit keys
x: 1
y: 2
r: 10
label: center/big
- # Merge one map
<< : *CENTER
r: 10
label: center/big
- # Merge multiple maps
<< : [ *CENTER, *BIG ]
label: center/big
- # Override
<< : [ *BIG, *LEFT, *SMALL ]
x: 1
label: center/big
`,
`
2019-11-05 17:02:55 +09:00
---
2019-10-16 18:21:20 +09:00
- &CENTER {x: 1, y: 2}
- &LEFT {x: 0, y: 2}
- &BIG {r: 10}
- &SMALL {r: 1}
- x: 1
y: 2
r: 10
label: center/big
- <<: *CENTER
r: 10
label: center/big
- <<: [*CENTER, *BIG]
label: center/big
- <<: [*BIG, *LEFT, *SMALL]
x: 1
label: center/big
`,
},
{
`
a:
- - b
- - c
- d
`,
`
a:
- - b
- - c
- d
`,
},
{
`
a:
b:
c: d
e:
f: g
h: i
j: k
`,
`
a:
b:
c: d
e:
f: g
h: i
j: k
2019-11-05 17:02:55 +09:00
`,
},
{
`
---
a: 1
b: 2
...
---
c: 3
d: 4
...
`,
`
---
a: 1
b: 2
...
---
c: 3
d: 4
...
2019-11-07 23:45:39 +09:00
`,
},
{
`
a:
b: |
{
[ 1, 2 ]
}
c: d
`,
`
a:
b: |
{
[ 1, 2 ]
}
c: d
2019-11-08 16:48:54 +09:00
`,
},
{
`
|
hoge
fuga
piyo`,
`
|
hoge
fuga
piyo
`,
},
{
`
a: |
bbbbbbb
ccccccc
d: eeeeeeeeeeeeeeeee
`,
`
a: |
bbbbbbb
ccccccc
d: eeeeeeeeeeeeeeeee
`,
},
{
`
a: b
c
`,
`
a: b c
`,
},
{
`
a:
b: c
`,
`
a:
b: c
`,
},
{
`
a: b
c: d
`,
`
a: b
c: d
2020-03-07 12:03:06 +09:00
`,
},
{
`
- ab - cd
- ef - gh
`,
`
- ab - cd
- ef - gh
`,
},
{
`
- 0 - 1
- 2 - 3
`,
`
- 0 - 1 - 2 - 3
`,
},
{
`
a - b - c: value
`,
`
a - b - c: value
2020-03-07 20:17:54 +09:00
`,
},
{
`
a:
-
b: c
d: e
-
f: g
h: i
`,
`
a:
- b: c
d: e
- f: g
h: i
2019-10-16 18:21:20 +09:00
`,
},
}
for _, test := range tests {
2019-10-21 12:53:30 +09:00
tokens := lexer.Tokenize(test.source)
2019-10-16 18:21:20 +09:00
tokens.Dump()
2019-11-05 17:02:55 +09:00
f, err := parser.Parse(tokens, 0)
2019-10-16 18:21:20 +09:00
if err != nil {
t.Fatalf("%+v", err)
}
var v Visitor
2019-11-05 17:02:55 +09:00
for _, doc := range f.Docs {
ast.Walk(&v, doc.Body)
2019-10-16 18:21:20 +09:00
}
2019-11-05 17:02:55 +09:00
expect := fmt.Sprintf("\n%+v\n", f)
2019-10-16 18:21:20 +09:00
if test.expect != expect {
t.Fatalf("unexpected output: [%s] != [%s]", test.expect, expect)
}
}
}
2019-12-22 11:50:07 +09:00
func TestNewLineChar(t *testing.T) {
for _, f := range []string{
"lf.yml",
"cr.yml",
"crlf.yml",
} {
2019-12-22 12:08:45 +09:00
ast, err := parser.ParseFile(filepath.Join("testdata", f), 0)
2019-12-22 11:59:24 +09:00
if err != nil {
2019-12-22 11:50:07 +09:00
t.Fatalf("%+v", err)
}
2019-12-22 11:59:24 +09:00
actual := fmt.Sprintf("%v\n", ast)
expect := `a: "a"
b: 1
`
if expect != actual {
t.Fatal("unexpected result")
}
2019-12-22 11:50:07 +09:00
}
}
func TestSyntaxError(t *testing.T) {
sources := []string{
"a:\n- b\n c: d\n e: f\n g: h",
}
for _, source := range sources {
2019-11-05 17:02:55 +09:00
_, err := parser.ParseBytes([]byte(source), 0)
if err == nil {
t.Fatal("cannot catch syntax error")
}
2019-10-23 13:30:22 +09:00
fmt.Printf("%v\n", err)
}
}
2020-05-28 21:39:06 +09:00
func TestComment(t *testing.T) {
2020-05-29 11:49:32 +09:00
tests := []struct {
name string
yaml string
}{
{
name: "map with comment",
yaml: `
2020-05-28 21:39:06 +09:00
# commentA
a: #commentB
# commentC
b: c # commentD
# commentE
d: e # commentF
# commentG
f: g # commentH
# commentI
f: g # commentJ
# commentK
2020-05-29 11:49:32 +09:00
`,
},
{
name: "sequence with comment",
yaml: `
# commentA
- a # commentB
# commentC
- b: # commentD
# commentE
- d # commentF
- e # commentG
# commentH
`,
},
{
name: "anchor and alias",
yaml: `
a: &x b # commentA
c: *x # commentB
`,
},
2020-05-28 21:39:06 +09:00
}
2020-05-29 11:49:32 +09:00
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
f, err := parser.ParseBytes([]byte(test.yaml), parser.ParseComments)
if err != nil {
t.Fatalf("%+v", err)
}
var v Visitor
for _, doc := range f.Docs {
ast.Walk(&v, doc.Body)
}
})
2020-05-28 21:39:06 +09:00
}
}
2019-10-16 18:21:20 +09:00
type Visitor struct {
}
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
tk := node.GetToken()
tk.Prev = nil
tk.Next = nil
2020-05-28 21:39:06 +09:00
if comment := node.GetComment(); comment != nil {
comment.Prev = nil
comment.Next = nil
}
2019-10-16 18:21:20 +09:00
return v
}