Skip to content
Snippets Groups Projects
Commit ea8660ba authored by Danis Kirasirov's avatar Danis Kirasirov
Browse files

add tests

parent 0baa3151
Branches
Tags
No related merge requests found
......@@ -120,19 +120,6 @@ func (ArrayType) IsEmpty(v interface{}) bool {
// return nil
//}
func (ArrayType) NonStrictConverter(_ context.Context, _ *Field, v interface{}) interface{} {
if v == nil {
return nil
}
// Если в данных хранится не слайс или массив, преобразуем в слайс из одного элемента
if arr := reflect.ValueOf(v); arr.Kind() != reflect.Slice && arr.Kind() != reflect.Array {
return []interface{}{v}
}
return v
}
func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkFunc, opts *WalkOptions) (interface{}, bool, error) {
var changed bool
params, ok := field.Params.(*ArrayParameters)
......@@ -147,9 +134,14 @@ func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkF
arr := reflect.ValueOf(v)
if v != nil && arr.Kind() != reflect.Slice && arr.Kind() != reflect.Array {
if !opts.WalkNonStrict {
return nil, false, fmt.Errorf("incorrect type: %s, expected array or slice", arr.Kind())
}
// При использовании опции WalkNonStrict преобразовываем в слайс
arr = reflect.ValueOf([]interface{}{v})
}
var length int
if v != nil {
length = arr.Len()
......
......@@ -67,6 +67,77 @@ func TestArrayField_Decode(t *testing.T) {
}
}
func TestArrayField_DecodeNonStrict(t *testing.T) {
tests := []struct {
name string
field *Field
data interface{}
want interface{}
wantErr bool
}{
{
"Nil data",
Array(Number(NumberFormatFloat)),
nil,
nil,
false,
},
{
"Correct data",
Array(Number(NumberFormatFloat)),
[]interface{}{1.0, 2.0},
[]interface{}{1.0, 2.0},
false,
},
{
"String as float",
Array(Number(NumberFormatFloat)),
[]interface{}{"1.0", "2.0"},
[]interface{}{1.0, 2.0},
false,
},
{
"String as int",
Array(Number("int")),
[]interface{}{"1", "2"},
[]interface{}{int64(1), int64(2)},
false,
},
{
"String as array",
Array(String()),
"string",
[]interface{}{"string"},
false,
},
{
"Single string number",
Array(Number("int")),
"2",
[]interface{}{int64(2)},
false,
},
{
"Incorrect data type",
Array(Number(NumberFormatInt)),
"1 2 3",
nil,
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Decode(context.Background(), tt.field, tt.data, NonStrictMode())
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.ElementsMatch(t, got, tt.want, "Decode() got = %v, want %v", got, tt.want)
})
}
}
func TestArrayField_Encode(t *testing.T) {
tests := []struct {
name string
......
......@@ -42,6 +42,10 @@ func NewEncodeOptions(opt ...EncodeOption) *EncodeOptions {
func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption) (interface{}, error) {
opt := NewEncodeOptions(opts...)
var walkOpts []WalkOption
if opt.NonStrictMode {
walkOpts = append(walkOpts, WalkNonStrict())
}
val, _, err := w.Walk(ctx, v, func(ctx context.Context, f *Field, v interface{}) (res WalkFuncResult, err error) {
if opt.NonStrictMode {
......@@ -60,7 +64,7 @@ func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption)
}
res.Value = v
return
})
}, walkOpts...)
if err != nil {
return nil, errors.Wrap(err, "decode error")
......
......@@ -100,6 +100,36 @@ func TestNumberField_Encode(t *testing.T) {
}
}
func TestNumberField_DecodeNonStrict(t *testing.T) {
tests := []struct {
name string
field *Field
data interface{}
want interface{}
wantErr bool
}{
{"Nil data", Number(NumberFormatInt), nil, nil, false},
{"Correct int", Number(NumberFormatInt), int64(2), int64(2), false},
{"Correct float", Number(NumberFormatFloat), 2.2, 2.2, false},
{"String as float", Number(NumberFormatFloat), "2.2", 2.2, false},
{"String as int", Number(NumberFormatInt), "2", int64(2), false},
{"Incorrect data", Number(NumberFormatInt), "invalid", nil, true},
{"Incorrect data type", Number(NumberFormatInt), []byte("invalid"), nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Decode(context.Background(), tt.field, tt.data, NonStrictMode())
if (err != nil) != tt.wantErr {
t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Decode() got = %v, want %v", got, tt.want)
}
})
}
}
// Добавлен полные функции, чтобы результаты теста не поменялись, в случае изменения Decode
// Реализация cast type.
func toNumber(i interface{}) (interface{}, error) {
......
......@@ -36,6 +36,35 @@ func TestStringField_Decode(t *testing.T) {
}
}
func TestStringField_DecodeNonStrict(t *testing.T) {
tests := []struct {
name string
field *Field
data interface{}
want interface{}
wantErr bool
}{
{"Correct", String(), "string", "string", false},
{"Nil", String(), nil, nil, false},
{"Int", String(), 42, "42", false},
{"Float", String(), 3.14, "3.14", false},
{"Bool", String(), true, "true", false},
{"Array", String(), []interface{}{1, "2"}, "[1 2]", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Decode(context.Background(), tt.field, tt.data, NonStrictMode())
if (err != nil) != tt.wantErr {
t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Decode() got = %v, want %v", got, tt.want)
}
})
}
}
func TestStringField_Encode(t *testing.T) {
tests := []struct {
name string
......
......@@ -23,6 +23,7 @@ type FieldWalker interface {
type WalkOptions struct {
WalkSchema bool
WalkNonStrict bool
}
type WalkOption func(opts *WalkOptions)
......@@ -36,6 +37,15 @@ func WalkSchema() WalkOption {
}
}
// WalkNonStrict указывает что обход может выполняться в нестрогом режиме.
// При обходе по данным в случае несоответствия их типа будет выполнена
// попытка преобразования типа с использованием NonStrictConverter.
func WalkNonStrict() WalkOption {
return func(opts *WalkOptions) {
opts.WalkNonStrict = true
}
}
func WalkOpts(o *WalkOptions) WalkOption {
return func(opts *WalkOptions) {
*opts = *o
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment