aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/go-cmp/cmp/cmpopts
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-03-12 11:24:17 +0100
committerDmitry Vyukov <dvyukov@google.com>2019-03-17 18:06:44 +0100
commitf51ae9765f195bb6491b604afec2002b5cbe668b (patch)
treef45e3860abab863d9352cc3c9e2800925fab4288 /vendor/github.com/google/go-cmp/cmp/cmpopts
parentba18afea77c0d9592eed8e49543982c3aafb2abf (diff)
vendor/github.com/google/go-cmp: update to HEAD
To pick up fix for: https://github.com/google/go-cmp/issues/103
Diffstat (limited to 'vendor/github.com/google/go-cmp/cmp/cmpopts')
-rw-r--r--vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go6
-rw-r--r--vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go73
-rw-r--r--vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go37
-rw-r--r--vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go46
-rw-r--r--vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go31
-rw-r--r--vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go35
6 files changed, 123 insertions, 105 deletions
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
index cc39492cf..41bbddc61 100644
--- a/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
@@ -17,7 +17,7 @@ func equateAlways(_, _ interface{}) bool { return true }
// EquateEmpty returns a Comparer option that determines all maps and slices
// with a length of zero to be equal, regardless of whether they are nil.
//
-// EquateEmpty can be used in conjuction with SortSlices and SortMaps.
+// EquateEmpty can be used in conjunction with SortSlices and SortMaps.
func EquateEmpty() cmp.Option {
return cmp.FilterValues(isEmpty, cmp.Comparer(equateAlways))
}
@@ -42,7 +42,7 @@ func isEmpty(x, y interface{}) bool {
// The mathematical expression used is equivalent to:
// |x-y| ≤ max(fraction*min(|x|, |y|), margin)
//
-// EquateApprox can be used in conjuction with EquateNaNs.
+// EquateApprox can be used in conjunction with EquateNaNs.
func EquateApprox(fraction, margin float64) cmp.Option {
if margin < 0 || fraction < 0 || math.IsNaN(margin) || math.IsNaN(fraction) {
panic("margin or fraction must be a non-negative number")
@@ -73,7 +73,7 @@ func (a approximator) compareF32(x, y float32) bool {
// EquateNaNs returns a Comparer option that determines float32 and float64
// NaN values to be equal.
//
-// EquateNaNs can be used in conjuction with EquateApprox.
+// EquateNaNs can be used in conjunction with EquateApprox.
func EquateNaNs() cmp.Option {
return cmp.Options{
cmp.FilterValues(areNaNsF64s, cmp.Comparer(equateAlways)),
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
index 016891da3..ff8e785d4 100644
--- a/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
@@ -11,6 +11,7 @@ import (
"unicode/utf8"
"github.com/google/go-cmp/cmp"
+ "github.com/google/go-cmp/cmp/internal/function"
)
// IgnoreFields returns an Option that ignores exported fields of the
@@ -50,7 +51,7 @@ func (tf typeFilter) filter(p cmp.Path) bool {
if len(p) < 1 {
return false
}
- t := p[len(p)-1].Type()
+ t := p.Last().Type()
for _, ti := range tf {
if t.AssignableTo(ti) {
return true
@@ -95,7 +96,7 @@ func (tf ifaceFilter) filter(p cmp.Path) bool {
if len(p) < 1 {
return false
}
- t := p[len(p)-1].Type()
+ t := p.Last().Type()
for _, ti := range tf {
if t.AssignableTo(ti) {
return true
@@ -112,6 +113,10 @@ func (tf ifaceFilter) filter(p cmp.Path) bool {
// In particular, unexported fields within the struct's exported fields
// of struct types, including anonymous fields, will not be ignored unless the
// type of the field itself is also passed to IgnoreUnexported.
+//
+// Avoid ignoring unexported fields of a type which you do not control (i.e. a
+// type from another repository), as changes to the implementation of such types
+// may change how the comparison behaves. Prefer a custom Comparer instead.
func IgnoreUnexported(typs ...interface{}) cmp.Option {
ux := newUnexportedFilter(typs...)
return cmp.FilterPath(ux.filter, cmp.Ignore())
@@ -131,14 +136,11 @@ func newUnexportedFilter(typs ...interface{}) unexportedFilter {
return ux
}
func (xf unexportedFilter) filter(p cmp.Path) bool {
- if len(p) < 2 {
- return false
- }
- sf, ok := p[len(p)-1].(cmp.StructField)
+ sf, ok := p.Index(-1).(cmp.StructField)
if !ok {
return false
}
- return xf.m[p[len(p)-2].Type()] && !isExported(sf.Name())
+ return xf.m[p.Index(-2).Type()] && !isExported(sf.Name())
}
// isExported reports whether the identifier is exported.
@@ -146,3 +148,60 @@ func isExported(id string) bool {
r, _ := utf8.DecodeRuneInString(id)
return unicode.IsUpper(r)
}
+
+// IgnoreSliceElements returns an Option that ignores elements of []V.
+// The discard function must be of the form "func(T) bool" which is used to
+// ignore slice elements of type V, where V is assignable to T.
+// Elements are ignored if the function reports true.
+func IgnoreSliceElements(discardFunc interface{}) cmp.Option {
+ vf := reflect.ValueOf(discardFunc)
+ if !function.IsType(vf.Type(), function.ValuePredicate) || vf.IsNil() {
+ panic(fmt.Sprintf("invalid discard function: %T", discardFunc))
+ }
+ return cmp.FilterPath(func(p cmp.Path) bool {
+ si, ok := p.Index(-1).(cmp.SliceIndex)
+ if !ok {
+ return false
+ }
+ if !si.Type().AssignableTo(vf.Type().In(0)) {
+ return false
+ }
+ vx, vy := si.Values()
+ if vx.IsValid() && vf.Call([]reflect.Value{vx})[0].Bool() {
+ return true
+ }
+ if vy.IsValid() && vf.Call([]reflect.Value{vy})[0].Bool() {
+ return true
+ }
+ return false
+ }, cmp.Ignore())
+}
+
+// IgnoreMapEntries returns an Option that ignores entries of map[K]V.
+// The discard function must be of the form "func(T, R) bool" which is used to
+// ignore map entries of type K and V, where K and V are assignable to T and R.
+// Entries are ignored if the function reports true.
+func IgnoreMapEntries(discardFunc interface{}) cmp.Option {
+ vf := reflect.ValueOf(discardFunc)
+ if !function.IsType(vf.Type(), function.KeyValuePredicate) || vf.IsNil() {
+ panic(fmt.Sprintf("invalid discard function: %T", discardFunc))
+ }
+ return cmp.FilterPath(func(p cmp.Path) bool {
+ mi, ok := p.Index(-1).(cmp.MapIndex)
+ if !ok {
+ return false
+ }
+ if !mi.Key().Type().AssignableTo(vf.Type().In(0)) || !mi.Type().AssignableTo(vf.Type().In(1)) {
+ return false
+ }
+ k := mi.Key()
+ vx, vy := mi.Values()
+ if vx.IsValid() && vf.Call([]reflect.Value{k, vx})[0].Bool() {
+ return true
+ }
+ if vy.IsValid() && vf.Call([]reflect.Value{k, vy})[0].Bool() {
+ return true
+ }
+ return false
+ }, cmp.Ignore())
+}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
index a566d240b..3a4804621 100644
--- a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
@@ -7,6 +7,7 @@ package cmpopts
import (
"fmt"
"reflect"
+ "sort"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/internal/function"
@@ -24,14 +25,14 @@ import (
// The less function does not have to be "total". That is, if !less(x, y) and
// !less(y, x) for two elements x and y, their relative order is maintained.
//
-// SortSlices can be used in conjuction with EquateEmpty.
-func SortSlices(less interface{}) cmp.Option {
- vf := reflect.ValueOf(less)
+// SortSlices can be used in conjunction with EquateEmpty.
+func SortSlices(lessFunc interface{}) cmp.Option {
+ vf := reflect.ValueOf(lessFunc)
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
- panic(fmt.Sprintf("invalid less function: %T", less))
+ panic(fmt.Sprintf("invalid less function: %T", lessFunc))
}
ss := sliceSorter{vf.Type().In(0), vf}
- return cmp.FilterValues(ss.filter, cmp.Transformer("Sort", ss.sort))
+ return cmp.FilterValues(ss.filter, cmp.Transformer("cmpopts.SortSlices", ss.sort))
}
type sliceSorter struct {
@@ -48,8 +49,8 @@ func (ss sliceSorter) filter(x, y interface{}) bool {
}
// Check whether the slices are already sorted to avoid an infinite
// recursion cycle applying the same transform to itself.
- ok1 := sliceIsSorted(x, func(i, j int) bool { return ss.less(vx, i, j) })
- ok2 := sliceIsSorted(y, func(i, j int) bool { return ss.less(vy, i, j) })
+ ok1 := sort.SliceIsSorted(x, func(i, j int) bool { return ss.less(vx, i, j) })
+ ok2 := sort.SliceIsSorted(y, func(i, j int) bool { return ss.less(vy, i, j) })
return !ok1 || !ok2
}
func (ss sliceSorter) sort(x interface{}) interface{} {
@@ -58,7 +59,7 @@ func (ss sliceSorter) sort(x interface{}) interface{} {
for i := 0; i < src.Len(); i++ {
dst.Index(i).Set(src.Index(i))
}
- sortSliceStable(dst.Interface(), func(i, j int) bool { return ss.less(dst, i, j) })
+ sort.SliceStable(dst.Interface(), func(i, j int) bool { return ss.less(dst, i, j) })
ss.checkSort(dst)
return dst.Interface()
}
@@ -95,14 +96,14 @@ func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
// • Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
// • Total: if x != y, then either less(x, y) or less(y, x)
//
-// SortMaps can be used in conjuction with EquateEmpty.
-func SortMaps(less interface{}) cmp.Option {
- vf := reflect.ValueOf(less)
+// SortMaps can be used in conjunction with EquateEmpty.
+func SortMaps(lessFunc interface{}) cmp.Option {
+ vf := reflect.ValueOf(lessFunc)
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
- panic(fmt.Sprintf("invalid less function: %T", less))
+ panic(fmt.Sprintf("invalid less function: %T", lessFunc))
}
ms := mapSorter{vf.Type().In(0), vf}
- return cmp.FilterValues(ms.filter, cmp.Transformer("Sort", ms.sort))
+ return cmp.FilterValues(ms.filter, cmp.Transformer("cmpopts.SortMaps", ms.sort))
}
type mapSorter struct {
@@ -118,7 +119,10 @@ func (ms mapSorter) filter(x, y interface{}) bool {
}
func (ms mapSorter) sort(x interface{}) interface{} {
src := reflect.ValueOf(x)
- outType := mapEntryType(src.Type())
+ outType := reflect.StructOf([]reflect.StructField{
+ {Name: "K", Type: src.Type().Key()},
+ {Name: "V", Type: src.Type().Elem()},
+ })
dst := reflect.MakeSlice(reflect.SliceOf(outType), src.Len(), src.Len())
for i, k := range src.MapKeys() {
v := reflect.New(outType).Elem()
@@ -126,7 +130,7 @@ func (ms mapSorter) sort(x interface{}) interface{} {
v.Field(1).Set(src.MapIndex(k))
dst.Index(i).Set(v)
}
- sortSlice(dst.Interface(), func(i, j int) bool { return ms.less(dst, i, j) })
+ sort.Slice(dst.Interface(), func(i, j int) bool { return ms.less(dst, i, j) })
ms.checkSort(dst)
return dst.Interface()
}
@@ -139,8 +143,5 @@ func (ms mapSorter) checkSort(v reflect.Value) {
}
func (ms mapSorter) less(v reflect.Value, i, j int) bool {
vx, vy := v.Index(i).Field(0), v.Index(j).Field(0)
- if !hasReflectStructOf {
- vx, vy = vx.Elem(), vy.Elem()
- }
return ms.fnc.Call([]reflect.Value{vx, vy})[0].Bool()
}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go
deleted file mode 100644
index 839b88ca4..000000000
--- a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017, The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE.md file.
-
-// +build !go1.8
-
-package cmpopts
-
-import (
- "reflect"
- "sort"
-)
-
-const hasReflectStructOf = false
-
-func mapEntryType(reflect.Type) reflect.Type {
- return reflect.TypeOf(struct{ K, V interface{} }{})
-}
-
-func sliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
- return sort.IsSorted(reflectSliceSorter{reflect.ValueOf(slice), less})
-}
-func sortSlice(slice interface{}, less func(i, j int) bool) {
- sort.Sort(reflectSliceSorter{reflect.ValueOf(slice), less})
-}
-func sortSliceStable(slice interface{}, less func(i, j int) bool) {
- sort.Stable(reflectSliceSorter{reflect.ValueOf(slice), less})
-}
-
-type reflectSliceSorter struct {
- slice reflect.Value
- less func(i, j int) bool
-}
-
-func (ss reflectSliceSorter) Len() int {
- return ss.slice.Len()
-}
-func (ss reflectSliceSorter) Less(i, j int) bool {
- return ss.less(i, j)
-}
-func (ss reflectSliceSorter) Swap(i, j int) {
- vi := ss.slice.Index(i).Interface()
- vj := ss.slice.Index(j).Interface()
- ss.slice.Index(i).Set(reflect.ValueOf(vj))
- ss.slice.Index(j).Set(reflect.ValueOf(vi))
-}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go
deleted file mode 100644
index 8a59c0d38..000000000
--- a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017, The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE.md file.
-
-// +build go1.8
-
-package cmpopts
-
-import (
- "reflect"
- "sort"
-)
-
-const hasReflectStructOf = true
-
-func mapEntryType(t reflect.Type) reflect.Type {
- return reflect.StructOf([]reflect.StructField{
- {Name: "K", Type: t.Key()},
- {Name: "V", Type: t.Elem()},
- })
-}
-
-func sliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
- return sort.SliceIsSorted(slice, less)
-}
-func sortSlice(slice interface{}, less func(i, j int) bool) {
- sort.Slice(slice, less)
-}
-func sortSliceStable(slice interface{}, less func(i, j int) bool) {
- sort.SliceStable(slice, less)
-}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go
new file mode 100644
index 000000000..9d651553d
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go
@@ -0,0 +1,35 @@
+// Copyright 2018, The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE.md file.
+
+package cmpopts
+
+import (
+ "github.com/google/go-cmp/cmp"
+)
+
+type xformFilter struct{ xform cmp.Option }
+
+func (xf xformFilter) filter(p cmp.Path) bool {
+ for _, ps := range p {
+ if t, ok := ps.(cmp.Transform); ok && t.Option() == xf.xform {
+ return false
+ }
+ }
+ return true
+}
+
+// AcyclicTransformer returns a Transformer with a filter applied that ensures
+// that the transformer cannot be recursively applied upon its own output.
+//
+// An example use case is a transformer that splits a string by lines:
+// AcyclicTransformer("SplitLines", func(s string) []string{
+// return strings.Split(s, "\n")
+// })
+//
+// Had this been an unfiltered Transformer instead, this would result in an
+// infinite cycle converting a string to []string to [][]string and so on.
+func AcyclicTransformer(name string, xformFunc interface{}) cmp.Option {
+ xf := xformFilter{cmp.Transformer(name, xformFunc)}
+ return cmp.FilterPath(xf.filter, xf.xform)
+}