validators: add ValidatorIntChoices

This commit is contained in:
Yousong Zhou
2020-01-10 13:58:08 +08:00
parent 60eb3bcbb2
commit 0c00b3ac98
3 changed files with 133 additions and 0 deletions
+12
View File
@@ -98,6 +98,18 @@ func newInvalidChoiceError(key string, choices choices.Choices, choice string) e
return newError(ERR_INVALID_CHOICE, "invalid %q, want %s, got %s", key, choices, choice)
}
func newInvalidIntChoiceError(key string, choices []int64, choice int64) error {
wantS := ""
for i, c := range choices {
if i > 0 {
wantS += ", "
}
wantS += fmt.Sprintf("%d", c)
}
gotS := fmt.Sprintf("%d", choice)
return newError(ERR_INVALID_CHOICE, "invalid %q, want %s, got %s", key, wantS, gotS)
}
func newStringTooShortError(key string, got, want int) error {
return newError(ERR_INVALID_LENGTH, "%q too short, got %d, min %s", key, got, want)
}
+54
View File
@@ -158,6 +158,60 @@ func (v *ValidatorIPv4Prefix) Validate(data *jsonutils.JSONDict) error {
return nil
}
type ValidatorIntChoices struct {
Validator
choices []int64
Value int64
}
func NewIntChoicesValidator(key string, choices []int64) *ValidatorIntChoices {
v := &ValidatorIntChoices{
Validator: Validator{Key: key},
choices: choices,
}
v.SetParent(v)
return v
}
func (v *ValidatorIntChoices) has(i int64) bool {
for _, c := range v.choices {
if c == i {
return true
}
}
return false
}
func (v *ValidatorIntChoices) Default(i int64) IValidator {
if v.has(i) {
v.Validator.Default(i)
return v
}
panic("invalid default for " + v.Key)
}
func (v *ValidatorIntChoices) getValue() interface{} {
return v.Value
}
func (v *ValidatorIntChoices) Validate(data *jsonutils.JSONDict) error {
if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
return err
}
i, err := v.value.Int()
if err != nil {
return newGeneralError(v.Key, err)
}
if !v.has(i) {
return newInvalidIntChoiceError(v.Key, v.choices, i)
}
// in case it's stringified from v.value
data.Set(v.Key, jsonutils.NewInt(i))
v.Value = i
return nil
}
type ValidatorStringChoices struct {
Validator
Choices choices.Choices
@@ -161,6 +161,73 @@ func TestStringChoicesValidator(t *testing.T) {
}
}
func TestIntChoicesValidator(t *testing.T) {
choices := []int64{-1, 0, 100}
cases := []*C{
{
Name: "missing non-optional",
In: `{}`,
Out: `{}`,
Optional: false,
Err: ERR_MISSING_KEY,
ValueWant: int64(0),
},
{
Name: "missing optional",
In: `{}`,
Out: `{}`,
Optional: true,
ValueWant: int64(0),
},
{
Name: "missing with default",
In: `{}`,
Out: `{s: -1}`,
Default: int64(-1),
ValueWant: int64(-1),
},
{
Name: "stringified",
In: `{"s": "100"}`,
Out: `{s: 100}`,
ValueWant: int64(100),
},
{
Name: "stringified invalid choice",
In: `{"s": "101"}`,
Out: `{"s": "101"}`,
Err: ERR_INVALID_CHOICE,
ValueWant: int64(0),
},
{
Name: "good choice",
In: `{"s": 0}`,
Out: `{"s": 0}`,
ValueWant: int64(0),
},
{
Name: "bad choice",
In: `{"s": 101}`,
Out: `{"s": 101}`,
Err: ERR_INVALID_CHOICE,
ValueWant: int64(0),
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
v := NewIntChoicesValidator("s", choices)
if c.Default != nil {
s := c.Default.(int64)
v.Default(s)
}
if c.Optional {
v.Optional(true)
}
testS(t, v, c)
})
}
}
func TestStringMultiChoicesValidator(t *testing.T) {
type MultiChoicesC struct {
*C