67
vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
generated
vendored
67
vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
generated
vendored
@@ -8,8 +8,10 @@ package cmpopts
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func equateAlways(_, _ interface{}) bool { return true }
|
||||
@@ -87,3 +89,68 @@ func areNaNsF64s(x, y float64) bool {
|
||||
func areNaNsF32s(x, y float32) bool {
|
||||
return areNaNsF64s(float64(x), float64(y))
|
||||
}
|
||||
|
||||
// EquateApproxTime returns a Comparer option that determines two non-zero
|
||||
// time.Time values to be equal if they are within some margin of one another.
|
||||
// If both times have a monotonic clock reading, then the monotonic time
|
||||
// difference will be used. The margin must be non-negative.
|
||||
func EquateApproxTime(margin time.Duration) cmp.Option {
|
||||
if margin < 0 {
|
||||
panic("margin must be a non-negative number")
|
||||
}
|
||||
a := timeApproximator{margin}
|
||||
return cmp.FilterValues(areNonZeroTimes, cmp.Comparer(a.compare))
|
||||
}
|
||||
|
||||
func areNonZeroTimes(x, y time.Time) bool {
|
||||
return !x.IsZero() && !y.IsZero()
|
||||
}
|
||||
|
||||
type timeApproximator struct {
|
||||
margin time.Duration
|
||||
}
|
||||
|
||||
func (a timeApproximator) compare(x, y time.Time) bool {
|
||||
// Avoid subtracting times to avoid overflow when the
|
||||
// difference is larger than the largest representible duration.
|
||||
if x.After(y) {
|
||||
// Ensure x is always before y
|
||||
x, y = y, x
|
||||
}
|
||||
// We're within the margin if x+margin >= y.
|
||||
// Note: time.Time doesn't have AfterOrEqual method hence the negation.
|
||||
return !x.Add(a.margin).Before(y)
|
||||
}
|
||||
|
||||
// AnyError is an error that matches any non-nil error.
|
||||
var AnyError anyError
|
||||
|
||||
type anyError struct{}
|
||||
|
||||
func (anyError) Error() string { return "any error" }
|
||||
func (anyError) Is(err error) bool { return err != nil }
|
||||
|
||||
// EquateErrors returns a Comparer option that determines errors to be equal
|
||||
// if errors.Is reports them to match. The AnyError error can be used to
|
||||
// match any non-nil error.
|
||||
func EquateErrors() cmp.Option {
|
||||
return cmp.FilterValues(areConcreteErrors, cmp.Comparer(compareErrors))
|
||||
}
|
||||
|
||||
// areConcreteErrors reports whether x and y are types that implement error.
|
||||
// The input types are deliberately of the interface{} type rather than the
|
||||
// error type so that we can handle situations where the current type is an
|
||||
// interface{}, but the underlying concrete types both happen to implement
|
||||
// the error interface.
|
||||
func areConcreteErrors(x, y interface{}) bool {
|
||||
_, ok1 := x.(error)
|
||||
_, ok2 := y.(error)
|
||||
return ok1 && ok2
|
||||
}
|
||||
|
||||
func compareErrors(x, y interface{}) bool {
|
||||
xe := x.(error)
|
||||
ye := y.(error)
|
||||
// TODO(≥go1.13): Use standard definition of errors.Is.
|
||||
return xerrors.Is(xe, ye) || xerrors.Is(ye, xe)
|
||||
}
|
||||
|
||||
71
vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
generated
vendored
71
vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
generated
vendored
@@ -11,16 +11,16 @@ 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
|
||||
// given names on a single struct type.
|
||||
// IgnoreFields returns an Option that ignores fields of the
|
||||
// given names on a single struct type. It respects the names of exported fields
|
||||
// that are forwarded due to struct embedding.
|
||||
// The struct type is specified by passing in a value of that type.
|
||||
//
|
||||
// The name may be a dot-delimited string (e.g., "Foo.Bar") to ignore a
|
||||
// specific sub-field that is embedded or nested within the parent struct.
|
||||
//
|
||||
// This does not handle unexported fields; use IgnoreUnexported instead.
|
||||
func IgnoreFields(typ interface{}, names ...string) cmp.Option {
|
||||
sf := newStructFilter(typ, names...)
|
||||
return cmp.FilterPath(sf.filter, cmp.Ignore())
|
||||
@@ -112,6 +112,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())
|
||||
@@ -124,7 +128,7 @@ func newUnexportedFilter(typs ...interface{}) unexportedFilter {
|
||||
for _, typ := range typs {
|
||||
t := reflect.TypeOf(typ)
|
||||
if t == nil || t.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("invalid struct type: %T", typ))
|
||||
panic(fmt.Sprintf("%T must be a non-pointer struct", typ))
|
||||
}
|
||||
ux.m[t] = true
|
||||
}
|
||||
@@ -143,3 +147,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())
|
||||
}
|
||||
|
||||
33
vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
generated
vendored
33
vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
generated
vendored
@@ -7,6 +7,7 @@ package cmpopts
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/internal/function"
|
||||
@@ -25,13 +26,13 @@ import (
|
||||
// !less(y, x) for two elements x and y, their relative order is maintained.
|
||||
//
|
||||
// SortSlices can be used in conjunction with EquateEmpty.
|
||||
func SortSlices(less interface{}) cmp.Option {
|
||||
vf := reflect.ValueOf(less)
|
||||
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()
|
||||
}
|
||||
@@ -96,13 +97,13 @@ func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
|
||||
// • Total: if x != y, then either less(x, y) or less(y, x)
|
||||
//
|
||||
// SortMaps can be used in conjunction with EquateEmpty.
|
||||
func SortMaps(less interface{}) cmp.Option {
|
||||
vf := reflect.ValueOf(less)
|
||||
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()
|
||||
}
|
||||
|
||||
46
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go
generated
vendored
46
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go
generated
vendored
@@ -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))
|
||||
}
|
||||
31
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go
generated
vendored
31
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go
generated
vendored
@@ -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)
|
||||
}
|
||||
19
vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go
generated
vendored
19
vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go
generated
vendored
@@ -42,7 +42,7 @@ func newStructFilter(typ interface{}, names ...string) structFilter {
|
||||
|
||||
t := reflect.TypeOf(typ)
|
||||
if t == nil || t.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("%T must be a struct", typ))
|
||||
panic(fmt.Sprintf("%T must be a non-pointer struct", typ))
|
||||
}
|
||||
var ft fieldTree
|
||||
for _, name := range names {
|
||||
@@ -160,14 +160,19 @@ func canonicalName(t reflect.Type, sel string) ([]string, error) {
|
||||
|
||||
// Find the canonical name for this current field name.
|
||||
// If the field exists in an embedded struct, then it will be expanded.
|
||||
sf, _ := t.FieldByName(name)
|
||||
if !isExported(name) {
|
||||
// Disallow unexported fields:
|
||||
// * To discourage people from actually touching unexported fields
|
||||
// * FieldByName is buggy (https://golang.org/issue/4876)
|
||||
return []string{name}, fmt.Errorf("name must be exported")
|
||||
// Avoid using reflect.Type.FieldByName for unexported fields due to
|
||||
// buggy behavior with regard to embeddeding and unexported fields.
|
||||
// See https://golang.org/issue/4876 for details.
|
||||
sf = reflect.StructField{}
|
||||
for i := 0; i < t.NumField() && sf.Name == ""; i++ {
|
||||
if t.Field(i).Name == name {
|
||||
sf = t.Field(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
sf, ok := t.FieldByName(name)
|
||||
if !ok {
|
||||
if sf.Name == "" {
|
||||
return []string{name}, fmt.Errorf("does not exist")
|
||||
}
|
||||
var ss []string
|
||||
|
||||
35
vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go
generated
vendored
Normal file
35
vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go
generated
vendored
Normal file
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user