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

add tests

parent 0baa3151
No related branches found
No related tags found
No related merge requests found
...@@ -120,19 +120,6 @@ func (ArrayType) IsEmpty(v interface{}) bool { ...@@ -120,19 +120,6 @@ func (ArrayType) IsEmpty(v interface{}) bool {
// return nil // 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) { func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkFunc, opts *WalkOptions) (interface{}, bool, error) {
var changed bool var changed bool
params, ok := field.Params.(*ArrayParameters) params, ok := field.Params.(*ArrayParameters)
...@@ -147,9 +134,14 @@ func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkF ...@@ -147,9 +134,14 @@ func (ArrayType) Walk(ctx context.Context, field *Field, v interface{}, fn WalkF
arr := reflect.ValueOf(v) arr := reflect.ValueOf(v)
if v != nil && arr.Kind() != reflect.Slice && arr.Kind() != reflect.Array { 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()) return nil, false, fmt.Errorf("incorrect type: %s, expected array or slice", arr.Kind())
} }
// При использовании опции WalkNonStrict преобразовываем в слайс
arr = reflect.ValueOf([]interface{}{v})
}
var length int var length int
if v != nil { if v != nil {
length = arr.Len() length = arr.Len()
......
...@@ -67,6 +67,77 @@ func TestArrayField_Decode(t *testing.T) { ...@@ -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) { func TestArrayField_Encode(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
......
...@@ -42,6 +42,10 @@ func NewEncodeOptions(opt ...EncodeOption) *EncodeOptions { ...@@ -42,6 +42,10 @@ func NewEncodeOptions(opt ...EncodeOption) *EncodeOptions {
func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption) (interface{}, error) { func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption) (interface{}, error) {
opt := NewEncodeOptions(opts...) 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) { val, _, err := w.Walk(ctx, v, func(ctx context.Context, f *Field, v interface{}) (res WalkFuncResult, err error) {
if opt.NonStrictMode { if opt.NonStrictMode {
...@@ -60,7 +64,7 @@ func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption) ...@@ -60,7 +64,7 @@ func Decode(ctx context.Context, w Walker, v interface{}, opts ...EncodeOption)
} }
res.Value = v res.Value = v
return return
}) }, walkOpts...)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "decode error") return nil, errors.Wrap(err, "decode error")
......
...@@ -100,6 +100,36 @@ func TestNumberField_Encode(t *testing.T) { ...@@ -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 // Добавлен полные функции, чтобы результаты теста не поменялись, в случае изменения Decode
// Реализация cast type. // Реализация cast type.
func toNumber(i interface{}) (interface{}, error) { func toNumber(i interface{}) (interface{}, error) {
......
...@@ -36,6 +36,35 @@ func TestStringField_Decode(t *testing.T) { ...@@ -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) { func TestStringField_Encode(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
......
...@@ -23,6 +23,7 @@ type FieldWalker interface { ...@@ -23,6 +23,7 @@ type FieldWalker interface {
type WalkOptions struct { type WalkOptions struct {
WalkSchema bool WalkSchema bool
WalkNonStrict bool
} }
type WalkOption func(opts *WalkOptions) type WalkOption func(opts *WalkOptions)
...@@ -36,6 +37,15 @@ func WalkSchema() WalkOption { ...@@ -36,6 +37,15 @@ func WalkSchema() WalkOption {
} }
} }
// WalkNonStrict указывает что обход может выполняться в нестрогом режиме.
// При обходе по данным в случае несоответствия их типа будет выполнена
// попытка преобразования типа с использованием NonStrictConverter.
func WalkNonStrict() WalkOption {
return func(opts *WalkOptions) {
opts.WalkNonStrict = true
}
}
func WalkOpts(o *WalkOptions) WalkOption { func WalkOpts(o *WalkOptions) WalkOption {
return func(opts *WalkOptions) { return func(opts *WalkOptions) {
*opts = *o *opts = *o
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment