summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2018-11-07 08:59:21 +0100
committerBjørn Erik Pedersen <[email protected]>2018-11-07 09:29:13 +0100
commit79a06aa4b64b526c242dfa41f2c7bc24e1352d5b (patch)
tree31b2b429bcb849f93d2abd492e5b08f45c80291d
parentd212f60949b6afefbe5aa79394f98dbddf7be068 (diff)
downloadhugo-79a06aa4b64b526c242dfa41f2c7bc24e1352d5b.tar.gz
hugo-79a06aa4b64b526c242dfa41f2c7bc24e1352d5b.zip
tpl/collections: Properly handle pointer types in complement/symdiff
We cannot compare them by values, because that gets `hash of unhashable type` for the prime use case.
-rw-r--r--tpl/collections/complement_test.go19
-rw-r--r--tpl/collections/reflect_helpers.go4
-rw-r--r--tpl/collections/symdiff_test.go8
3 files changed, 20 insertions, 11 deletions
diff --git a/tpl/collections/complement_test.go b/tpl/collections/complement_test.go
index 4cae7556f..e5edb23d3 100644
--- a/tpl/collections/complement_test.go
+++ b/tpl/collections/complement_test.go
@@ -23,6 +23,13 @@ import (
"github.com/stretchr/testify/require"
)
+type StructWithSlice struct {
+ A string
+ B []string
+}
+
+type StructWithSlicePointers []*StructWithSlice
+
func TestComplement(t *testing.T) {
t.Parallel()
@@ -33,10 +40,13 @@ func TestComplement(t *testing.T) {
s1 := []TstX{TstX{A: "a"}, TstX{A: "b"}, TstX{A: "d"}, TstX{A: "e"}}
s2 := []TstX{TstX{A: "b"}, TstX{A: "e"}}
- xa, xd := &TstX{A: "a"}, &TstX{A: "d"}
+ xa, xb, xd, xe := &StructWithSlice{A: "a"}, &StructWithSlice{A: "b"}, &StructWithSlice{A: "d"}, &StructWithSlice{A: "e"}
+
+ sp1 := []*StructWithSlice{xa, xb, xd, xe}
+ sp2 := []*StructWithSlice{xb, xe}
- sp1 := []*TstX{xa, &TstX{A: "b"}, xd, &TstX{A: "e"}}
- sp2 := []*TstX{&TstX{A: "b"}, &TstX{A: "e"}}
+ sp1_2 := StructWithSlicePointers{xa, xb, xd, xe}
+ sp2_2 := StructWithSlicePointers{xb, xe}
for i, test := range []struct {
s interface{}
@@ -49,7 +59,8 @@ func TestComplement(t *testing.T) {
{[]int{1, 2, 3, 4, 5}, []interface{}{[]int{1, 3}, []string{"a", "b"}, []int{1, 2}}, []int{4, 5}},
{[]int{1, 2, 3, 4, 5}, []interface{}{[]int64{1, 3}}, []int{2, 4, 5}},
{s1, []interface{}{s2}, []TstX{TstX{A: "a"}, TstX{A: "d"}}},
- {sp1, []interface{}{sp2}, []*TstX{xa, xd}},
+ {sp1, []interface{}{sp2}, []*StructWithSlice{xa, xd}},
+ {sp1_2, []interface{}{sp2_2}, StructWithSlicePointers{xa, xd}},
// Errors
{[]string{"a", "b", "c"}, []interface{}{"error"}, false},
diff --git a/tpl/collections/reflect_helpers.go b/tpl/collections/reflect_helpers.go
index 85aa389ce..fca65481f 100644
--- a/tpl/collections/reflect_helpers.go
+++ b/tpl/collections/reflect_helpers.go
@@ -43,7 +43,6 @@ func numberToFloat(v reflect.Value) (float64, error) {
}
// normalizes different numeric types to make them comparable.
-// If not, any pointer will be unwrapped.
func normalize(v reflect.Value) interface{} {
k := v.Kind()
@@ -53,8 +52,6 @@ func normalize(v reflect.Value) interface{} {
if err == nil {
return f
}
- case k == reflect.Ptr:
- v = v.Elem()
}
return v.Interface()
@@ -70,6 +67,7 @@ func collectIdentities(seqs ...interface{}) (map[interface{}]bool, error) {
case reflect.Array, reflect.Slice:
for i := 0; i < v.Len(); i++ {
ev, _ := indirectInterface(v.Index(i))
+
if !ev.Type().Comparable() {
return nil, errors.New("elements must be comparable")
}
diff --git a/tpl/collections/symdiff_test.go b/tpl/collections/symdiff_test.go
index d44999730..4024ffe7a 100644
--- a/tpl/collections/symdiff_test.go
+++ b/tpl/collections/symdiff_test.go
@@ -33,10 +33,10 @@ func TestSymDiff(t *testing.T) {
s1 := []TstX{TstX{A: "a"}, TstX{A: "b"}}
s2 := []TstX{TstX{A: "a"}, TstX{A: "e"}}
- xa, xd := &TstX{A: "a"}, &TstX{A: "d"}
+ xa, xb, xd, xe := &StructWithSlice{A: "a"}, &StructWithSlice{A: "b"}, &StructWithSlice{A: "d"}, &StructWithSlice{A: "e"}
- sp1 := []*TstX{xa, &TstX{A: "b"}, xd, &TstX{A: "e"}}
- sp2 := []*TstX{&TstX{A: "b"}, &TstX{A: "e"}}
+ sp1 := []*StructWithSlice{xa, xb, xd, xe}
+ sp2 := []*StructWithSlice{xb, xe}
for i, test := range []struct {
s1 interface{}
@@ -49,7 +49,7 @@ func TestSymDiff(t *testing.T) {
{[]int{1, 2, 3}, []int{3, 4}, []int{1, 2, 4}},
{[]int{1, 2, 3}, []int64{3, 4}, []int{1, 2, 4}},
{s1, s2, []TstX{TstX{A: "b"}, TstX{A: "e"}}},
- {sp1, sp2, []*TstX{xa, xd}},
+ {sp1, sp2, []*StructWithSlice{xa, xd}},
// Errors
{"error", "error", false},