VOL-3190 throw error message when filter or order on struct
Change-Id: If15983350d3f1a6fd21e5bfcec33ae57808cc31f
diff --git a/VERSION b/VERSION
index 2bf1ca5..0659a5b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.7
+1.1.8-dev
diff --git a/pkg/filter/filter.go b/pkg/filter/filter.go
index 2498fa2..ffab11e 100644
--- a/pkg/filter/filter.go
+++ b/pkg/filter/filter.go
@@ -166,7 +166,7 @@
}
if val.Kind() != reflect.Struct {
- return false, fmt.Errorf("Dotted field name specified in filter did not resolve to a valid field")
+ return false, fmt.Errorf("Field name specified in filter did not resolve to a valid field")
}
field := val.FieldByName(k)
@@ -174,6 +174,15 @@
return false, fmt.Errorf("Failed to find field %s while filtering", k)
}
+ // we might have a pointer to a struct at this time, so dereference it
+ if field.Kind() == reflect.Ptr {
+ field = reflect.Indirect(field)
+ }
+
+ if field.Kind() == reflect.Struct {
+ return false, fmt.Errorf("Cannot filter on a field that is a struct")
+ }
+
if (field.Kind() == reflect.Slice) || (field.Kind() == reflect.Array) {
// For an array, check to see if any item matches
someMatch := false
diff --git a/pkg/filter/filter_test.go b/pkg/filter/filter_test.go
index 874bda3..d08811d 100644
--- a/pkg/filter/filter_test.go
+++ b/pkg/filter/filter_test.go
@@ -30,10 +30,11 @@
Two string
Three string
Five TestFilterIncludedStruct
+ Seven *TestFilterIncludedStruct
}
func TestFilterList(t *testing.T) {
- f, err := Parse("One=a,Two=b,Five.Six=d")
+ f, err := Parse("One=a,Two=b,Five.Six=d,Seven.Six=e")
if err != nil {
t.Errorf("Unable to parse filter: %s", err.Error())
}
@@ -44,18 +45,21 @@
Two: "b",
Three: "c",
Five: TestFilterIncludedStruct{Six: "d"},
+ Seven: &TestFilterIncludedStruct{Six: "e"},
},
TestFilterStruct{
One: "1",
Two: "2",
Three: "3",
Five: TestFilterIncludedStruct{Six: "4"},
+ Seven: &TestFilterIncludedStruct{Six: "5"},
},
TestFilterStruct{
One: "a",
Two: "b",
Three: "z",
Five: TestFilterIncludedStruct{Six: "d"},
+ Seven: &TestFilterIncludedStruct{Six: "e"},
},
}
@@ -231,7 +235,7 @@
}
r, err := f.Process(data)
- assert.EqualError(t, err, "Dotted field name specified in filter did not resolve to a valid field")
+ assert.EqualError(t, err, "Field name specified in filter did not resolve to a valid field")
if r != nil {
t.Errorf("expected no results, got some")
@@ -252,7 +256,49 @@
}
r, err := f.Process(data)
- assert.EqualError(t, err, "Dotted field name specified in filter did not resolve to a valid field")
+ assert.EqualError(t, err, "Field name specified in filter did not resolve to a valid field")
+
+ if r != nil {
+ t.Errorf("expected no results, got some")
+ }
+}
+
+func TestFilterOnStruct(t *testing.T) {
+ f, err := Parse("Five=a")
+ if err != nil {
+ t.Errorf("Unable to parse filter: %s", err.Error())
+ }
+
+ data := TestFilterStruct{
+ One: "a",
+ Two: "b",
+ Three: "c",
+ Five: TestFilterIncludedStruct{Six: "w"},
+ }
+
+ r, err := f.Process(data)
+ assert.EqualError(t, err, "Cannot filter on a field that is a struct")
+
+ if r != nil {
+ t.Errorf("expected no results, got some")
+ }
+}
+
+func TestFilterOnPointerStruct(t *testing.T) {
+ f, err := Parse("Seven=a")
+ if err != nil {
+ t.Errorf("Unable to parse filter: %s", err.Error())
+ }
+
+ data := TestFilterStruct{
+ One: "a",
+ Two: "b",
+ Three: "c",
+ Seven: &TestFilterIncludedStruct{Six: "w"},
+ }
+
+ r, err := f.Process(data)
+ assert.EqualError(t, err, "Cannot filter on a field that is a struct")
if r != nil {
t.Errorf("expected no results, got some")
diff --git a/pkg/order/order.go b/pkg/order/order.go
index bcf097b..09ef1fc 100644
--- a/pkg/order/order.go
+++ b/pkg/order/order.go
@@ -110,6 +110,16 @@
if !field.IsValid() {
return field, fmt.Errorf("Failed to find field %s while sorting", name)
}
+
+ // we might have a pointer to a struct at this time, so dereference it
+ if field.Kind() == reflect.Ptr {
+ field = reflect.Indirect(field)
+ }
+
+ if field.Kind() == reflect.Struct {
+ return val, fmt.Errorf("Cannot sort on a field that is a struct")
+ }
+
return field, nil
}
diff --git a/pkg/order/order_test.go b/pkg/order/order_test.go
index 28132d9..f2d28b4 100644
--- a/pkg/order/order_test.go
+++ b/pkg/order/order_test.go
@@ -32,6 +32,7 @@
Three uint
Four int
Six SortIncludedStruct
+ Eight *SortIncludedStruct
}
var testSetOne = []SortTestStruct{
@@ -42,6 +43,7 @@
Three: 10,
Four: 1,
Six: SortIncludedStruct{Seven: "o"},
+ Eight: &SortIncludedStruct{Seven: "o"},
},
{
Id: 1,
@@ -50,6 +52,7 @@
Three: 1,
Four: 10,
Six: SortIncludedStruct{Seven: "p"},
+ Eight: &SortIncludedStruct{Seven: "p"},
},
{
Id: 2,
@@ -58,6 +61,7 @@
Three: 2,
Four: 1000,
Six: SortIncludedStruct{Seven: "q"},
+ Eight: &SortIncludedStruct{Seven: "q"},
},
{
Id: 3,
@@ -66,6 +70,7 @@
Three: 3,
Four: 100,
Six: SortIncludedStruct{Seven: "r"},
+ Eight: &SortIncludedStruct{Seven: "r"},
},
{
Id: 4,
@@ -74,6 +79,7 @@
Three: 3,
Four: 0,
Six: SortIncludedStruct{Seven: "s"},
+ Eight: &SortIncludedStruct{Seven: "s"},
},
}
@@ -272,7 +278,22 @@
}
}
-func TestInvaliodDotted(t *testing.T) {
+func TestSortDottedPointer(t *testing.T) {
+ s, err := Parse("+Eight.Seven")
+ if err != nil {
+ t.Errorf("Unable to parse sort specification")
+ }
+ o, err := s.Process(testSetOne)
+ if err != nil {
+ t.Errorf("Sort failed: %s", err.Error())
+ }
+
+ if !Verify(o.([]SortTestStruct), []int{0, 1, 2, 3, 4}) {
+ t.Errorf("incorrect sort")
+ }
+}
+
+func TestInvalidDotted(t *testing.T) {
s, err := Parse("+Six.Nonexistent")
if err != nil {
t.Errorf("Unable to parse sort specification")
@@ -296,6 +317,30 @@
}
}
+func TestSortOnStuct(t *testing.T) {
+ s, err := Parse("+Six")
+ if err != nil {
+ t.Errorf("Unable to parse sort specification")
+ }
+ o, err := s.Process(testSetOne)
+ assert.EqualError(t, err, "Cannot sort on a field that is a struct")
+ if o != nil {
+ t.Errorf("expected no results, got some")
+ }
+}
+
+func TestSortOnPointerStuct(t *testing.T) {
+ s, err := Parse("+Eight")
+ if err != nil {
+ t.Errorf("Unable to parse sort specification")
+ }
+ o, err := s.Process(testSetOne)
+ assert.EqualError(t, err, "Cannot sort on a field that is a struct")
+ if o != nil {
+ t.Errorf("expected no results, got some")
+ }
+}
+
func TestTrailingDot(t *testing.T) {
s, err := Parse("+Six.Seven.")
if err != nil {