go-yaml/yaml_test.go

469 lines
8.1 KiB
Go
Raw Normal View History

2019-10-18 13:05:36 +09:00
package yaml_test
import (
2020-03-02 23:11:18 +09:00
"bytes"
2019-10-18 13:05:36 +09:00
"testing"
"github.com/goccy/go-yaml"
2020-03-02 23:11:18 +09:00
"github.com/goccy/go-yaml/ast"
"golang.org/x/xerrors"
2019-10-18 13:05:36 +09:00
)
2019-10-19 18:28:36 +09:00
func TestMarshal(t *testing.T) {
var v struct {
A int
B string
}
v.A = 1
v.B = "hello"
bytes, err := yaml.Marshal(v)
if err != nil {
t.Fatalf("%+v", err)
}
if string(bytes) != "a: 1\nb: hello\n" {
t.Fatal("failed to marshal")
}
}
2019-10-18 13:05:36 +09:00
func TestUnmarshal(t *testing.T) {
yml := `
%YAML 1.2
---
a: 1
b: c
`
var v struct {
A int
B string
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
t.Fatalf("%+v", err)
}
}
type marshalTest struct{}
func (t *marshalTest) MarshalYAML() ([]byte, error) {
return yaml.Marshal(yaml.MapSlice{
{
"a", 1,
},
{
"b", "hello",
},
{
"c", true,
},
{
"d", map[string]string{"x": "y"},
},
})
}
type marshalTest2 struct{}
func (t *marshalTest2) MarshalYAML() (interface{}, error) {
return yaml.MapSlice{
{
"a", 2,
},
{
"b", "world",
},
{
"c", true,
},
}, nil
}
func TestMarshalYAML(t *testing.T) {
var v struct {
A *marshalTest
B *marshalTest2
}
v.A = &marshalTest{}
v.B = &marshalTest2{}
bytes, err := yaml.Marshal(v)
if err != nil {
t.Fatalf("failed to Marshal: %+v", err)
}
expect := `
a:
a: 1
b: hello
c: true
d:
x: y
b:
a: 2
b: world
c: true
`
actual := "\n" + string(bytes)
if expect != actual {
t.Fatalf("failed to MarshalYAML expect:[%s], actual:[%s]", expect, actual)
}
}
2019-10-24 17:18:03 +09:00
type unmarshalTest struct {
a int
b string
c bool
}
func (t *unmarshalTest) UnmarshalYAML(b []byte) error {
if t.a != 0 {
return xerrors.New("unexpected field value to a")
}
if t.b != "" {
return xerrors.New("unexpected field value to b")
}
if t.c {
return xerrors.New("unexpected field value to c")
}
var v struct {
A int
B string
C bool
}
if err := yaml.Unmarshal(b, &v); err != nil {
return err
}
t.a = v.A
t.b = v.B
t.c = v.C
return nil
}
type unmarshalTest2 struct {
a int
b string
c bool
}
func (t *unmarshalTest2) UnmarshalYAML(unmarshal func(interface{}) error) error {
2019-10-24 17:18:03 +09:00
var v struct {
A int
B string
C bool
}
if t.a != 0 {
return xerrors.New("unexpected field value to a")
}
if t.b != "" {
return xerrors.New("unexpected field value to b")
}
if t.c {
return xerrors.New("unexpected field value to c")
}
if err := unmarshal(&v); err != nil {
return err
}
t.a = v.A
t.b = v.B
t.c = v.C
return nil
}
func TestUnmarshalYAML(t *testing.T) {
yml := `
a:
a: 1
b: hello
c: true
b:
a: 2
b: world
c: true
2019-10-24 17:18:03 +09:00
`
var v struct {
A *unmarshalTest
B *unmarshalTest2
2019-10-24 17:18:03 +09:00
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
t.Fatalf("failed to Unmarshal: %+v", err)
}
if v.A == nil {
t.Fatal("failed to UnmarshalYAML")
}
if v.A.a != 1 {
t.Fatal("failed to UnmarshalYAML")
}
if v.A.b != "hello" {
t.Fatal("failed to UnmarshalYAML")
}
if !v.A.c {
t.Fatal("failed to UnmarshalYAML")
}
if v.B == nil {
t.Fatal("failed to UnmarshalYAML")
}
if v.B.a != 2 {
t.Fatal("failed to UnmarshalYAML")
}
if v.B.b != "world" {
t.Fatal("failed to UnmarshalYAML")
}
if !v.B.c {
t.Fatal("failed to UnmarshalYAML")
}
2019-10-24 17:18:03 +09:00
}
2020-03-02 23:11:18 +09:00
type ObjectMap map[string]*Object
type ObjectDecl struct {
Name string `yaml:"-"`
*Object `yaml:",inline,anchor"`
}
func (m ObjectMap) MarshalYAML() (interface{}, error) {
newMap := map[string]*ObjectDecl{}
for k, v := range m {
newMap[k] = &ObjectDecl{Name: k, Object: v}
}
return newMap, nil
}
type rootObject struct {
Single ObjectMap `yaml:"single"`
Collection map[string][]*Object `yaml:"collection"`
}
type Object struct {
*Object `yaml:",omitempty,inline,alias"`
MapValue map[string]interface{} `yaml:",omitempty,inline"`
}
func TestInlineAnchorAndAlias(t *testing.T) {
yml := `---
single:
default: &default
id: 1
name: john
user_1: &user_1
id: 1
name: ken
user_2: &user_2
<<: *default
id: 2
collection:
defaults:
- *default
- <<: *default
- <<: *default
id: 2
users:
- <<: *user_1
- <<: *user_2
- <<: *user_1
id: 3
- <<: *user_1
id: 4
- <<: *user_1
id: 5
`
var v rootObject
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
2020-06-22 23:44:26 +09:00
t.Fatal(err)
2020-03-02 23:11:18 +09:00
}
opt := yaml.MarshalAnchor(func(anchor *ast.AnchorNode, value interface{}) error {
if o, ok := value.(*ObjectDecl); ok {
2020-06-22 23:44:26 +09:00
return anchor.SetName(o.Name)
2020-03-02 23:11:18 +09:00
}
return nil
})
var buf bytes.Buffer
if err := yaml.NewEncoder(&buf, opt).Encode(v); err != nil {
t.Fatalf("%+v", err)
}
actual := "---\n" + buf.String()
if yml != actual {
t.Fatalf("failed to marshal: expected:[%s] actual:[%s]", yml, actual)
}
}
2020-06-21 16:20:46 +09:00
func TestMapSlice_Map(t *testing.T) {
yml := `
a: b
c: d
`
var v yaml.MapSlice
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
t.Fatal(err)
}
m := v.ToMap()
if len(m) != 2 {
t.Fatal("failed to convert MapSlice to map")
}
if m["a"] != "b" {
t.Fatal("failed to convert MapSlice to map")
}
if m["c"] != "d" {
t.Fatal("failed to convert MapSlice to map")
}
}
2020-06-22 23:30:51 +09:00
func TestMarshalWithModifiedAnchorAlias(t *testing.T) {
yml := `
a: &a 1
b: *a
`
var v struct {
A *int `yaml:"a,anchor"`
B *int `yaml:"b,alias"`
}
if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
t.Fatal(err)
}
node, err := yaml.ValueToNode(v)
if err != nil {
t.Fatal(err)
}
anchors := ast.Filter(ast.AnchorType, node)
if len(anchors) != 1 {
t.Fatal("failed to filter node")
}
anchor := anchors[0].(*ast.AnchorNode)
if err := anchor.SetName("b"); err != nil {
t.Fatal(err)
}
aliases := ast.Filter(ast.AliasType, node)
if len(anchors) != 1 {
t.Fatal("failed to filter node")
}
alias := aliases[0].(*ast.AliasNode)
if err := alias.SetName("b"); err != nil {
t.Fatal(err)
}
expected := `
a: &b 1
b: *b`
actual := "\n" + node.String()
if expected != actual {
t.Fatalf("failed to marshal: expected:[%q] but got [%q]", expected, actual)
}
}
2020-10-26 19:00:29 +09:00
func Test_YAMLToJSON(t *testing.T) {
yml := `
foo:
bar:
- a
- b
- c
a: 1
`
actual, err := yaml.YAMLToJSON([]byte(yml))
if err != nil {
t.Fatal(err)
}
expected := `{"foo": {"bar": ["a", "b", "c"]}, "a": 1}`
if expected+"\n" != string(actual) {
t.Fatalf("failed to convert yaml to json: expected [%q] but got [%q]", expected, actual)
}
}
func Test_JSONToYAML(t *testing.T) {
json := `{"foo": {"bar": ["a", "b", "c"]}, "a": 1}`
expected := `
foo:
bar:
- a
- b
- c
a: 1
`
actual, err := yaml.JSONToYAML([]byte(json))
if err != nil {
t.Fatal(err)
}
if expected != "\n"+string(actual) {
t.Fatalf("failed to convert json to yaml: expected [%q] but got [%q]", expected, actual)
}
}
2021-07-20 14:26:02 +09:00
func Test_CommentMapOption(t *testing.T) {
v := struct {
Foo string `yaml:"foo"`
Bar map[string]interface{} `yaml:"bar"`
Baz struct {
X int `yaml:"x"`
} `yaml:"baz"`
}{
Foo: "aaa",
Bar: map[string]interface{}{"bbb": "ccc"},
Baz: struct {
X int `yaml:"x"`
}{X: 10},
}
t.Run("line comment", func(t *testing.T) {
b, err := yaml.MarshalWithOptions(v, yaml.WithComment(
yaml.CommentMap{
"$.foo": yaml.LineComment("foo comment"),
"$.bar": yaml.LineComment("bar comment"),
"$.bar.bbb": yaml.LineComment("bbb comment"),
"$.baz.x": yaml.LineComment("x comment"),
},
))
if err != nil {
t.Fatal(err)
}
expected := `
foo: aaa #foo comment
bar: #bar comment
bbb: ccc #bbb comment
baz:
x: 10 #x comment
`
actual := "\n" + string(b)
if expected != actual {
t.Fatalf("expected:%s but got %s", expected, actual)
}
})
t.Run("head comment", func(t *testing.T) {
b, err := yaml.MarshalWithOptions(v, yaml.WithComment(
yaml.CommentMap{
"$.foo": yaml.HeadComment(
"foo comment",
"foo comment2",
),
"$.bar": yaml.HeadComment(
"bar comment",
"bar comment2",
),
"$.bar.bbb": yaml.HeadComment(
"bbb comment",
"bbb comment2",
),
"$.baz.x": yaml.HeadComment(
"x comment",
"x comment2",
),
},
))
if err != nil {
t.Fatal(err)
}
expected := `
#foo comment
#foo comment2
foo: aaa
#bar comment
#bar comment2
bar:
#bbb comment
#bbb comment2
bbb: ccc
baz:
#x comment
#x comment2
x: 10
`
actual := "\n" + string(b)
if expected != actual {
t.Fatalf("expected:%s but got %s", expected, actual)
}
})
}