2019-10-26 10:08:44 +09:00
|
|
|
package yaml_test
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"strings"
|
2020-06-28 22:14:36 +03:00
|
|
|
"testing"
|
2019-10-26 10:08:44 +09:00
|
|
|
|
2020-11-01 12:53:27 +09:00
|
|
|
"github.com/go-playground/validator/v10"
|
2019-10-26 10:08:44 +09:00
|
|
|
"github.com/goccy/go-yaml"
|
|
|
|
|
)
|
|
|
|
|
|
2020-06-28 22:14:36 +03:00
|
|
|
func TestStructValidator(t *testing.T) {
|
2021-08-10 03:38:16 -04:00
|
|
|
type Inner struct {
|
|
|
|
|
Required string `validate:"required"`
|
|
|
|
|
Lt10 int `validate:"lt=10"`
|
|
|
|
|
}
|
2019-10-26 10:08:44 +09:00
|
|
|
|
2020-06-28 22:14:36 +03:00
|
|
|
cases := []struct {
|
|
|
|
|
TestName string
|
|
|
|
|
YAMLContent string
|
|
|
|
|
ExpectedErr string
|
|
|
|
|
Instance interface{}
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
TestName: "Test Simple Validation",
|
|
|
|
|
YAMLContent: `---
|
2019-10-26 10:08:44 +09:00
|
|
|
- name: john
|
|
|
|
|
age: 20
|
|
|
|
|
- name: tom
|
|
|
|
|
age: -1
|
|
|
|
|
- name: ken
|
2020-06-28 22:14:36 +03:00
|
|
|
age: 10`,
|
|
|
|
|
ExpectedErr: `[5:8] Key: 'Age' Error:Field validation for 'Age' failed on the 'gte' tag
|
|
|
|
|
2 | - name: john
|
|
|
|
|
3 | age: 20
|
|
|
|
|
4 | - name: tom
|
|
|
|
|
> 5 | age: -1
|
|
|
|
|
^
|
|
|
|
|
6 | - name: ken
|
|
|
|
|
7 | age: 10`,
|
|
|
|
|
Instance: &[]struct {
|
2021-04-24 18:01:36 -04:00
|
|
|
Name string `yaml:"name" validate:"required"`
|
|
|
|
|
Age int `yaml:"age" validate:"gte=0,lt=120"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
TestName: "Test Missing Required Field",
|
|
|
|
|
YAMLContent: `---
|
|
|
|
|
- name: john
|
|
|
|
|
age: 20
|
|
|
|
|
- age: 10`,
|
|
|
|
|
ExpectedErr: `[4:1] Key: 'Name' Error:Field validation for 'Name' failed on the 'required' tag
|
|
|
|
|
1 | ---
|
|
|
|
|
2 | - name: john
|
|
|
|
|
3 | age: 20
|
|
|
|
|
> 4 | - age: 10
|
|
|
|
|
^
|
|
|
|
|
`,
|
|
|
|
|
Instance: &[]struct {
|
2020-06-28 22:14:36 +03:00
|
|
|
Name string `yaml:"name" validate:"required"`
|
|
|
|
|
Age int `yaml:"age" validate:"gte=0,lt=120"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
TestName: "Test Nested Validation Missing Internal Required",
|
|
|
|
|
YAMLContent: `---
|
|
|
|
|
name: john
|
|
|
|
|
age: 10
|
|
|
|
|
addr:
|
|
|
|
|
number: seven`,
|
2021-04-24 17:06:35 -04:00
|
|
|
ExpectedErr: `[4:5] Key: 'State' Error:Field validation for 'State' failed on the 'required' tag
|
|
|
|
|
1 | ---
|
|
|
|
|
2 | name: john
|
|
|
|
|
3 | age: 10
|
|
|
|
|
> 4 | addr:
|
|
|
|
|
^
|
|
|
|
|
5 | number: seven`,
|
2020-06-28 22:14:36 +03:00
|
|
|
Instance: &struct {
|
|
|
|
|
Name string `yaml:"name" validate:"required"`
|
|
|
|
|
Age int `yaml:"age" validate:"gte=0,lt=120"`
|
|
|
|
|
Addr struct {
|
|
|
|
|
Number string `yaml:"number" validate:"required"`
|
|
|
|
|
State string `yaml:"state" validate:"required"`
|
|
|
|
|
} `yaml:"addr"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
2020-07-12 18:56:22 +03:00
|
|
|
{
|
|
|
|
|
TestName: "Test nested Validation with unknown field",
|
|
|
|
|
YAMLContent: `---
|
|
|
|
|
name: john
|
|
|
|
|
age: 20
|
|
|
|
|
addr:
|
|
|
|
|
number: seven
|
|
|
|
|
state: washington
|
|
|
|
|
error: error
|
|
|
|
|
`,
|
|
|
|
|
ExpectedErr: `[7:3] unknown field "error"
|
|
|
|
|
4 | addr:
|
|
|
|
|
5 | number: seven
|
|
|
|
|
6 | state: washington
|
|
|
|
|
> 7 | error: error
|
|
|
|
|
^
|
|
|
|
|
`,
|
|
|
|
|
Instance: &struct {
|
|
|
|
|
Name string `yaml:"name" validate:"required"`
|
|
|
|
|
Age int `yaml:"age" validate:"gte=0,lt=120"`
|
|
|
|
|
Addr *struct {
|
|
|
|
|
Number string `yaml:"number" validate:"required"`
|
|
|
|
|
State string `yaml:"state" validate:"required"`
|
|
|
|
|
} `yaml:"addr" validate:"required"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
2021-06-25 12:34:27 -04:00
|
|
|
{
|
|
|
|
|
TestName: "Test Validation with wrong field type",
|
|
|
|
|
YAMLContent: `---
|
|
|
|
|
name: myDocument
|
|
|
|
|
roles:
|
|
|
|
|
name: myRole
|
|
|
|
|
permissions:
|
|
|
|
|
- hello
|
|
|
|
|
- how
|
|
|
|
|
- are
|
|
|
|
|
- you
|
|
|
|
|
`,
|
2021-06-29 16:33:16 -04:00
|
|
|
ExpectedErr: `[4:7] mapping was used where sequence is expected
|
2021-06-25 12:34:27 -04:00
|
|
|
1 | ---
|
|
|
|
|
2 | name: myDocument
|
|
|
|
|
3 | roles:
|
|
|
|
|
> 4 | name: myRole
|
|
|
|
|
^
|
|
|
|
|
5 | permissions:
|
|
|
|
|
6 | - hello
|
|
|
|
|
7 | - how
|
|
|
|
|
8 | `,
|
|
|
|
|
Instance: &struct {
|
|
|
|
|
Name string `yaml:"name"`
|
|
|
|
|
Roles []struct {
|
|
|
|
|
Name string `yaml:"name"`
|
|
|
|
|
Permissions []string `yaml:"permissions"`
|
|
|
|
|
} `yaml:"roles"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
2021-08-10 03:38:16 -04:00
|
|
|
{
|
|
|
|
|
TestName: "Test inline validation missing required",
|
|
|
|
|
YAMLContent: `---
|
|
|
|
|
name: john
|
|
|
|
|
age: 20
|
|
|
|
|
`,
|
|
|
|
|
ExpectedErr: `Key: 'Inner.Required' Error:Field validation for 'Required' failed on the 'required' tag`,
|
|
|
|
|
Instance: &struct {
|
|
|
|
|
Name string `yaml:"name" validate:"required"`
|
|
|
|
|
Age int `yaml:"age" validate:"gte=0,lt=120"`
|
|
|
|
|
Inner `yaml:",inline"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
TestName: "Test inline validation field error",
|
|
|
|
|
YAMLContent: `---
|
|
|
|
|
name: john
|
|
|
|
|
age: 20
|
|
|
|
|
required: present
|
|
|
|
|
lt10: 20
|
|
|
|
|
`,
|
|
|
|
|
ExpectedErr: `[5:7] Key: 'Inner.Lt10' Error:Field validation for 'Lt10' failed on the 'lt' tag
|
|
|
|
|
2 | name: john
|
|
|
|
|
3 | age: 20
|
|
|
|
|
4 | required: present
|
|
|
|
|
> 5 | lt10: 20
|
|
|
|
|
^
|
|
|
|
|
`,
|
|
|
|
|
Instance: &struct {
|
|
|
|
|
Name string `yaml:"name" validate:"required"`
|
|
|
|
|
Age int `yaml:"age" validate:"gte=0,lt=120"`
|
|
|
|
|
Inner `yaml:",inline"`
|
|
|
|
|
}{},
|
|
|
|
|
},
|
2020-06-28 22:14:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
|
tc := tc // NOTE: https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
|
|
|
|
|
t.Run(tc.TestName, func(t *testing.T) {
|
|
|
|
|
validate := validator.New()
|
|
|
|
|
dec := yaml.NewDecoder(
|
|
|
|
|
strings.NewReader(tc.YAMLContent),
|
|
|
|
|
yaml.Validator(validate),
|
2020-07-12 18:56:22 +03:00
|
|
|
yaml.Strict(),
|
2020-06-28 22:14:36 +03:00
|
|
|
)
|
|
|
|
|
err := dec.Decode(tc.Instance)
|
|
|
|
|
switch {
|
|
|
|
|
case tc.ExpectedErr != "" && err == nil:
|
|
|
|
|
t.Fatal("expected error")
|
|
|
|
|
case tc.ExpectedErr == "" && err != nil:
|
|
|
|
|
t.Fatalf("unexpected error: %v", err)
|
|
|
|
|
case tc.ExpectedErr != "" && tc.ExpectedErr != err.Error():
|
|
|
|
|
t.Fatalf("expected `%s` but actual `%s`", tc.ExpectedErr, err.Error())
|
|
|
|
|
}
|
|
|
|
|
})
|
2019-10-26 10:08:44 +09:00
|
|
|
}
|
|
|
|
|
}
|