From 9b2f2ce58d6e74e215ff13708dcf6d4c2393880c Mon Sep 17 00:00:00 2001 From: okravchu Date: Fri, 3 Jun 2022 19:40:09 +0300 Subject: [PATCH 1/4] FEX-4347 Add filtering for dynamic field --- filter.go | 29 ++++ filter_test.go | 445 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 474 insertions(+) create mode 100644 filter_test.go diff --git a/filter.go b/filter.go index 07045f0..a6437ab 100644 --- a/filter.go +++ b/filter.go @@ -2,6 +2,7 @@ package relay import ( "errors" + "fmt" "reflect" "strconv" "strings" @@ -271,6 +272,34 @@ func markRecords(filterConditions string, val reflect.Value, arraySlice map[int] return nil, errors.New("Filter [" + ColumnStruct[1] + "] Column is not primitive type") } + } else if CurField.Kind() == reflect.Slice { + if len(ColumnStruct) < 2 { + continue + } + fieldName := ColumnStruct[1] + + var fieldValueExists bool + for i := 0; i < CurField.Len(); i++ { + element := CurField.Index(i) + + if !element.IsValid() { + return nil, fmt.Errorf("Filter [%s] No such column exist!!!", fieldName) + } + + if element.FieldByName("ID").String() == fieldName { + fieldValueExists = true + if isPrimitive(element.FieldByName("ID")) { + if bMatched, err = processPrimitive(element.FieldByName("Value"), Key, Op); err != nil { + return nil, err + } + } else { + return nil, fmt.Errorf("Filter [%s] Column is not primitive type", fieldName) + } + } + } + if !fieldValueExists { + return nil, fmt.Errorf("Filter [%s] No such column exist!!!", fieldName) + } } arraySlice[k] = DataSet{bMatched: bMatched, CurRec: arraySlice[k].CurRec} } diff --git a/filter_test.go b/filter_test.go new file mode 100644 index 0000000..42cd4ca --- /dev/null +++ b/filter_test.go @@ -0,0 +1,445 @@ +package relay + +import ( + "reflect" + "testing" +) + +type Data struct { + SomeID string `json:"someId"` + OutOfSupport bool `json:"outOfSupport"` + DynamicFields []DynamicFieldType `json:"dynamicField"` + SliceField []string `json:"sliceField"` +} + +type DynamicFieldType struct { + ID string `json:"id"` + Value string `json:"value"` +} + +func Test_markRecords(t *testing.T) { + type args struct { + filterConditions string + val reflect.Value + arraySlice map[int]DataSet + } + tests := []struct { + name string + args args + want map[int]DataSet + wantErr bool + }{ + { + name: "marked, multiple filters", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}&{key:true,column:outOfSupport,op:==}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: true, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "marked, primitive type", + args: args{ + filterConditions: "{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: true, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "not marked, primitive not match", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:4,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "not marked, dynamicFields values not match", + args: args{ + filterConditions: "{key:someValue1,column:dynamicFields.someID}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "marked, dynamicFields values match, contains", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: true, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "not marked, dynamicFields values not match, ===", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID,op:===}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "err, field not found", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID_1}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: nil, + wantErr: true, + }, + { + name: "err dynamic field name not provided", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + SliceField: []string{"some"}, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: nil, + wantErr: true, + }, + { + name: "", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + SliceField: []string{"some"}, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + SliceField: []string{"some"}, + }, + }, + }, + wantErr: false, + }, + { + name: "not marked, missing id", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := markRecords(tt.args.filterConditions, tt.args.val, tt.args.arraySlice) + if (err != nil) != tt.wantErr { + t.Errorf("markRecords() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("markRecords() got = %v, want %v", got, tt.want) + } + }) + } +} From bc69bb5c1dd383f3e24ca6bf18b5efd43eb50cac Mon Sep 17 00:00:00 2001 From: okravchu Date: Mon, 6 Jun 2022 09:50:11 +0300 Subject: [PATCH 2/4] FEX-4347 Add filtering for dynamic field, refactor --- filter.go | 42 ++++++++++--------- filter_test.go | 108 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 24 deletions(-) diff --git a/filter.go b/filter.go index a6437ab..575d270 100644 --- a/filter.go +++ b/filter.go @@ -277,30 +277,20 @@ func markRecords(filterConditions string, val reflect.Value, arraySlice map[int] continue } fieldName := ColumnStruct[1] + if fieldName == "" { + return nil, errors.New("Filter applied to slice column but inner field not specified") + } - var fieldValueExists bool for i := 0; i < CurField.Len(); i++ { - element := CurField.Index(i) - - if !element.IsValid() { - return nil, fmt.Errorf("Filter [%s] No such column exist!!!", fieldName) - } + item := CurField.Index(i) - if element.FieldByName("ID").String() == fieldName { - fieldValueExists = true - if isPrimitive(element.FieldByName("ID")) { - if bMatched, err = processPrimitive(element.FieldByName("Value"), Key, Op); err != nil { - return nil, err - } - } else { - return nil, fmt.Errorf("Filter [%s] Column is not primitive type", fieldName) - } + bMatched, err = itemMatches(item, fieldName, Key, Op) + if err != nil { + return nil, err } } - if !fieldValueExists { - return nil, fmt.Errorf("Filter [%s] No such column exist!!!", fieldName) - } } + arraySlice[k] = DataSet{bMatched: bMatched, CurRec: arraySlice[k].CurRec} } } @@ -308,6 +298,22 @@ func markRecords(filterConditions string, val reflect.Value, arraySlice map[int] return arraySlice, nil } +func itemMatches(item reflect.Value, fieldName, key, op string) (bool, error) { + if !item.IsValid() { + return false, fmt.Errorf("Filter [%s] No such column exist!!!", fieldName) + } + + if item.FieldByName("ID").String() != fieldName { + return false, nil + } + + if !isPrimitive(item.FieldByName("ID")) { + return false, fmt.Errorf("Filter [%s] Column is not primitive type", fieldName) + } + + return processPrimitive(item.FieldByName("Value"), key, op) +} + func isPrimitive(CurField reflect.Value) bool { switch CurField.Kind() { case reflect.Bool, reflect.String, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int32, reflect.Int64: diff --git a/filter_test.go b/filter_test.go index 42cd4ca..59f4c4c 100644 --- a/filter_test.go +++ b/filter_test.go @@ -29,6 +29,73 @@ func Test_markRecords(t *testing.T) { want map[int]DataSet wantErr bool }{ + { + name: "marked and not marked, multiple filters", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}&{key:true,column:outOfSupport,op:==}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID_2", + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: true, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + }, + 1: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID_2", + Value: "someValue", + }, + }, + }, + }, + }, + wantErr: false, + }, { name: "marked, multiple filters", args: args{ @@ -294,7 +361,7 @@ func Test_markRecords(t *testing.T) { wantErr: false, }, { - name: "err, field not found", + name: "field not found, not marked", args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID_1}&{key:5,column:SomeID}", val: func() reflect.Value { @@ -320,11 +387,25 @@ func Test_markRecords(t *testing.T) { return arraySliceRS }(), }, - want: nil, - wantErr: true, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue1", + }, + }, + }, + }, + }, + wantErr: false, }, { - name: "err dynamic field name not provided", + name: "dynamic field name not provided", args: args{ filterConditions: "{key:someValue,column:dynamicFields.}&{key:5,column:SomeID}", val: func() reflect.Value { @@ -417,6 +498,7 @@ func Test_markRecords(t *testing.T) { Value: "someValue", }, }, + SliceField: []string{"some"}, }, } arraySliceRS := make(map[int]DataSet) @@ -426,8 +508,22 @@ func Test_markRecords(t *testing.T) { return arraySliceRS }(), }, - want: nil, - wantErr: true, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + Value: "someValue", + }, + }, + SliceField: []string{"some"}, + }, + }, + }, + wantErr: false, }, } for _, tt := range tests { From 46069116a883e9e15e8b8869dea56e1b1748229c Mon Sep 17 00:00:00 2001 From: okravchu Date: Mon, 6 Jun 2022 17:10:44 +0300 Subject: [PATCH 3/4] Update tests --- filter.go | 4 +- filter_test.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 118 insertions(+), 7 deletions(-) diff --git a/filter.go b/filter.go index 575d270..a23265d 100644 --- a/filter.go +++ b/filter.go @@ -307,8 +307,8 @@ func itemMatches(item reflect.Value, fieldName, key, op string) (bool, error) { return false, nil } - if !isPrimitive(item.FieldByName("ID")) { - return false, fmt.Errorf("Filter [%s] Column is not primitive type", fieldName) + if !isPrimitive(item.FieldByName("Value")) { + return false, fmt.Errorf("Filter [%s] Value is not primitive type", fieldName) } return processPrimitive(item.FieldByName("Value"), key, op) diff --git a/filter_test.go b/filter_test.go index 59f4c4c..2b69f8b 100644 --- a/filter_test.go +++ b/filter_test.go @@ -30,9 +30,9 @@ func Test_markRecords(t *testing.T) { wantErr bool }{ { - name: "marked and not marked, multiple filters", + name: "marked and not marked, dynamic ID not match, multiple filters", args: args{ - filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}&{key:true,column:outOfSupport,op:==}", + filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}", val: func() reflect.Value { return reflect.Indirect(reflect.ValueOf(&Data{})) }(), @@ -96,6 +96,73 @@ func Test_markRecords(t *testing.T) { }, wantErr: false, }, + { + name: "marked and not marked, dynamic Value not match, multiple filters", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID,op:===}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue_2", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: true, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue", + }, + }, + }, + }, + 1: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + Value: "someValue_2", + }, + }, + }, + }, + }, + wantErr: false, + }, { name: "marked, multiple filters", args: args{ @@ -229,7 +296,7 @@ func Test_markRecords(t *testing.T) { wantErr: false, }, { - name: "not marked, dynamicFields values not match", + name: "not marked, dynamicFields ID not match", args: args{ filterConditions: "{key:someValue1,column:dynamicFields.someID}&{key:5,column:SomeID}", val: func() reflect.Value { @@ -405,7 +472,7 @@ func Test_markRecords(t *testing.T) { wantErr: false, }, { - name: "dynamic field name not provided", + name: "error, dynamic field name not provided", args: args{ filterConditions: "{key:someValue,column:dynamicFields.}&{key:5,column:SomeID}", val: func() reflect.Value { @@ -436,7 +503,7 @@ func Test_markRecords(t *testing.T) { wantErr: true, }, { - name: "", + name: "not marked, no field, skipping item", args: args{ filterConditions: "{key:someValue,column:dynamicFields}", val: func() reflect.Value { @@ -525,6 +592,50 @@ func Test_markRecords(t *testing.T) { }, wantErr: false, }, + { + name: "not marked, no value", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&Data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + }, + }, + SliceField: []string{"some"}, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: map[int]DataSet{ + 0: { + bMatched: false, + CurRec: Data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldType{ + { + ID: "someID", + }, + }, + SliceField: []string{"some"}, + }, + }, + }, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From ec799e3107b8a6dcc3ad95c9b993cc28a88c0f10 Mon Sep 17 00:00:00 2001 From: okravchu Date: Mon, 6 Jun 2022 17:22:28 +0300 Subject: [PATCH 4/4] Add test cases --- filter_test.go | 200 +++++++++++++++++++++++++++++++------------------ 1 file changed, 126 insertions(+), 74 deletions(-) diff --git a/filter_test.go b/filter_test.go index 2b69f8b..1c9a2e6 100644 --- a/filter_test.go +++ b/filter_test.go @@ -5,18 +5,30 @@ import ( "testing" ) -type Data struct { +type data struct { SomeID string `json:"someId"` OutOfSupport bool `json:"outOfSupport"` - DynamicFields []DynamicFieldType `json:"dynamicField"` + DynamicFields []dynamicFieldType `json:"dynamicField"` SliceField []string `json:"sliceField"` } -type DynamicFieldType struct { +type dynamicFieldType struct { ID string `json:"id"` Value string `json:"value"` } +type dataNotPrimitiveValue struct { + SomeID string `json:"someId"` + OutOfSupport bool `json:"outOfSupport"` + DynamicFields []DynamicFieldTypeNotPrimitiveValue `json:"dynamicField"` + SliceField []string `json:"sliceField"` +} + +type DynamicFieldTypeNotPrimitiveValue struct { + ID string `json:"id"` + Value []string `json:"value"` +} + func Test_markRecords(t *testing.T) { type args struct { filterConditions string @@ -34,24 +46,24 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", }, }, }, - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID_2", Value: "someValue", @@ -69,10 +81,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: true, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -82,10 +94,10 @@ func Test_markRecords(t *testing.T) { }, 1: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID_2", Value: "someValue", @@ -101,24 +113,24 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID,op:===}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", }, }, }, - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue_2", @@ -136,10 +148,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: true, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -149,10 +161,10 @@ func Test_markRecords(t *testing.T) { }, 1: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue_2", @@ -168,14 +180,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}&{key:true,column:outOfSupport,op:==}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -193,10 +205,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: true, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -212,14 +224,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -237,10 +249,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: true, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -256,14 +268,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:4,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -281,10 +293,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -300,14 +312,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue1,column:dynamicFields.someID}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -325,10 +337,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -344,14 +356,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -369,10 +381,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: true, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -388,14 +400,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID,op:===}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -413,10 +425,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -432,14 +444,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID_1}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -457,10 +469,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -476,14 +488,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.}&{key:5,column:SomeID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue1", @@ -507,14 +519,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -533,10 +545,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", Value: "someValue", @@ -553,14 +565,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { Value: "someValue", }, @@ -578,10 +590,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { Value: "someValue", }, @@ -597,14 +609,14 @@ func Test_markRecords(t *testing.T) { args: args{ filterConditions: "{key:someValue,column:dynamicFields.someID}", val: func() reflect.Value { - return reflect.Indirect(reflect.ValueOf(&Data{})) + return reflect.Indirect(reflect.ValueOf(&data{})) }(), arraySlice: func() map[int]DataSet { arraySlice := []interface{}{ - Data{ + data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", }, @@ -622,10 +634,10 @@ func Test_markRecords(t *testing.T) { want: map[int]DataSet{ 0: { bMatched: false, - CurRec: Data{ + CurRec: data{ SomeID: "5", OutOfSupport: true, - DynamicFields: []DynamicFieldType{ + DynamicFields: []dynamicFieldType{ { ID: "someID", }, @@ -636,6 +648,46 @@ func Test_markRecords(t *testing.T) { }, wantErr: false, }, + { + name: "error, not primitive value", + args: args{ + filterConditions: "{key:someValue,column:dynamicFields.someID}&{key:5,column:SomeID}", + val: func() reflect.Value { + return reflect.Indirect(reflect.ValueOf(&data{})) + }(), + arraySlice: func() map[int]DataSet { + arraySlice := []interface{}{ + dataNotPrimitiveValue{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []DynamicFieldTypeNotPrimitiveValue{ + { + ID: "someID", + Value: []string{"someValue"}, + }, + }, + }, + data{ + SomeID: "5", + OutOfSupport: true, + DynamicFields: []dynamicFieldType{ + { + ID: "someID_2", + Value: "someValue", + }, + }, + }, + } + arraySliceRS := make(map[int]DataSet) + for ind := range arraySlice { + arraySliceRS[ind] = DataSet{bMatched: false, CurRec: arraySlice[ind]} + } + return arraySliceRS + }(), + }, + want: nil, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {