aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/google/go-cmp
diff options
context:
space:
mode:
authorNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
committerNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
commit107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch)
treeca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/google/go-cmp
parent844b5a68d8af4791755b8f0ad293cc99f5959183 (diff)
downloadterraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/google/go-cmp')
-rw-r--r--vendor/github.com/google/go-cmp/LICENSE27
-rw-r--r--vendor/github.com/google/go-cmp/cmp/compare.go553
-rw-r--r--vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go17
-rw-r--r--vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go122
-rw-r--r--vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go363
-rw-r--r--vendor/github.com/google/go-cmp/cmp/internal/function/func.go49
-rw-r--r--vendor/github.com/google/go-cmp/cmp/internal/value/format.go277
-rw-r--r--vendor/github.com/google/go-cmp/cmp/internal/value/sort.go111
-rw-r--r--vendor/github.com/google/go-cmp/cmp/options.go453
-rw-r--r--vendor/github.com/google/go-cmp/cmp/path.go309
-rw-r--r--vendor/github.com/google/go-cmp/cmp/reporter.go53
-rw-r--r--vendor/github.com/google/go-cmp/cmp/unsafe_panic.go15
-rw-r--r--vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go23
13 files changed, 2372 insertions, 0 deletions
diff --git a/vendor/github.com/google/go-cmp/LICENSE b/vendor/github.com/google/go-cmp/LICENSE
new file mode 100644
index 0000000..32017f8
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/LICENSE
@@ -0,0 +1,27 @@
1Copyright (c) 2017 The Go Authors. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are
5met:
6
7 * Redistributions of source code must retain the above copyright
8notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10copyright notice, this list of conditions and the following disclaimer
11in the documentation and/or other materials provided with the
12distribution.
13 * Neither the name of Google Inc. nor the names of its
14contributors may be used to endorse or promote products derived from
15this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/google/go-cmp/cmp/compare.go b/vendor/github.com/google/go-cmp/cmp/compare.go
new file mode 100644
index 0000000..7e215f2
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/compare.go
@@ -0,0 +1,553 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// Package cmp determines equality of values.
6//
7// This package is intended to be a more powerful and safer alternative to
8// reflect.DeepEqual for comparing whether two values are semantically equal.
9//
10// The primary features of cmp are:
11//
12// • When the default behavior of equality does not suit the needs of the test,
13// custom equality functions can override the equality operation.
14// For example, an equality function may report floats as equal so long as they
15// are within some tolerance of each other.
16//
17// • Types that have an Equal method may use that method to determine equality.
18// This allows package authors to determine the equality operation for the types
19// that they define.
20//
21// • If no custom equality functions are used and no Equal method is defined,
22// equality is determined by recursively comparing the primitive kinds on both
23// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported
24// fields are not compared by default; they result in panics unless suppressed
25// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly compared
26// using the AllowUnexported option.
27package cmp
28
29import (
30 "fmt"
31 "reflect"
32
33 "github.com/google/go-cmp/cmp/internal/diff"
34 "github.com/google/go-cmp/cmp/internal/function"
35 "github.com/google/go-cmp/cmp/internal/value"
36)
37
38// BUG(dsnet): Maps with keys containing NaN values cannot be properly compared due to
39// the reflection package's inability to retrieve such entries. Equal will panic
40// anytime it comes across a NaN key, but this behavior may change.
41//
42// See https://golang.org/issue/11104 for more details.
43
44var nothing = reflect.Value{}
45
46// Equal reports whether x and y are equal by recursively applying the
47// following rules in the given order to x and y and all of their sub-values:
48//
49// • If two values are not of the same type, then they are never equal
50// and the overall result is false.
51//
52// • Let S be the set of all Ignore, Transformer, and Comparer options that
53// remain after applying all path filters, value filters, and type filters.
54// If at least one Ignore exists in S, then the comparison is ignored.
55// If the number of Transformer and Comparer options in S is greater than one,
56// then Equal panics because it is ambiguous which option to use.
57// If S contains a single Transformer, then use that to transform the current
58// values and recursively call Equal on the output values.
59// If S contains a single Comparer, then use that to compare the current values.
60// Otherwise, evaluation proceeds to the next rule.
61//
62// • If the values have an Equal method of the form "(T) Equal(T) bool" or
63// "(T) Equal(I) bool" where T is assignable to I, then use the result of
64// x.Equal(y) even if x or y is nil.
65// Otherwise, no such method exists and evaluation proceeds to the next rule.
66//
67// • Lastly, try to compare x and y based on their basic kinds.
68// Simple kinds like booleans, integers, floats, complex numbers, strings, and
69// channels are compared using the equivalent of the == operator in Go.
70// Functions are only equal if they are both nil, otherwise they are unequal.
71// Pointers are equal if the underlying values they point to are also equal.
72// Interfaces are equal if their underlying concrete values are also equal.
73//
74// Structs are equal if all of their fields are equal. If a struct contains
75// unexported fields, Equal panics unless the AllowUnexported option is used or
76// an Ignore option (e.g., cmpopts.IgnoreUnexported) ignores that field.
77//
78// Arrays, slices, and maps are equal if they are both nil or both non-nil
79// with the same length and the elements at each index or key are equal.
80// Note that a non-nil empty slice and a nil slice are not equal.
81// To equate empty slices and maps, consider using cmpopts.EquateEmpty.
82// Map keys are equal according to the == operator.
83// To use custom comparisons for map keys, consider using cmpopts.SortMaps.
84func Equal(x, y interface{}, opts ...Option) bool {
85 s := newState(opts)
86 s.compareAny(reflect.ValueOf(x), reflect.ValueOf(y))
87 return s.result.Equal()
88}
89
90// Diff returns a human-readable report of the differences between two values.
91// It returns an empty string if and only if Equal returns true for the same
92// input values and options. The output string will use the "-" symbol to
93// indicate elements removed from x, and the "+" symbol to indicate elements
94// added to y.
95//
96// Do not depend on this output being stable.
97func Diff(x, y interface{}, opts ...Option) string {
98 r := new(defaultReporter)
99 opts = Options{Options(opts), r}
100 eq := Equal(x, y, opts...)
101 d := r.String()
102 if (d == "") != eq {
103 panic("inconsistent difference and equality results")
104 }
105 return d
106}
107
108type state struct {
109 // These fields represent the "comparison state".
110 // Calling statelessCompare must not result in observable changes to these.
111 result diff.Result // The current result of comparison
112 curPath Path // The current path in the value tree
113 reporter reporter // Optional reporter used for difference formatting
114
115 // dynChecker triggers pseudo-random checks for option correctness.
116 // It is safe for statelessCompare to mutate this value.
117 dynChecker dynChecker
118
119 // These fields, once set by processOption, will not change.
120 exporters map[reflect.Type]bool // Set of structs with unexported field visibility
121 opts Options // List of all fundamental and filter options
122}
123
124func newState(opts []Option) *state {
125 s := new(state)
126 for _, opt := range opts {
127 s.processOption(opt)
128 }
129 return s
130}
131
132func (s *state) processOption(opt Option) {
133 switch opt := opt.(type) {
134 case nil:
135 case Options:
136 for _, o := range opt {
137 s.processOption(o)
138 }
139 case coreOption:
140 type filtered interface {
141 isFiltered() bool
142 }
143 if fopt, ok := opt.(filtered); ok && !fopt.isFiltered() {
144 panic(fmt.Sprintf("cannot use an unfiltered option: %v", opt))
145 }
146 s.opts = append(s.opts, opt)
147 case visibleStructs:
148 if s.exporters == nil {
149 s.exporters = make(map[reflect.Type]bool)
150 }
151 for t := range opt {
152 s.exporters[t] = true
153 }
154 case reporter:
155 if s.reporter != nil {
156 panic("difference reporter already registered")
157 }
158 s.reporter = opt
159 default:
160 panic(fmt.Sprintf("unknown option %T", opt))
161 }
162}
163
164// statelessCompare compares two values and returns the result.
165// This function is stateless in that it does not alter the current result,
166// or output to any registered reporters.
167func (s *state) statelessCompare(vx, vy reflect.Value) diff.Result {
168 // We do not save and restore the curPath because all of the compareX
169 // methods should properly push and pop from the path.
170 // It is an implementation bug if the contents of curPath differs from
171 // when calling this function to when returning from it.
172
173 oldResult, oldReporter := s.result, s.reporter
174 s.result = diff.Result{} // Reset result
175 s.reporter = nil // Remove reporter to avoid spurious printouts
176 s.compareAny(vx, vy)
177 res := s.result
178 s.result, s.reporter = oldResult, oldReporter
179 return res
180}
181
182func (s *state) compareAny(vx, vy reflect.Value) {
183 // TODO: Support cyclic data structures.
184
185 // Rule 0: Differing types are never equal.
186 if !vx.IsValid() || !vy.IsValid() {
187 s.report(vx.IsValid() == vy.IsValid(), vx, vy)
188 return
189 }
190 if vx.Type() != vy.Type() {
191 s.report(false, vx, vy) // Possible for path to be empty
192 return
193 }
194 t := vx.Type()
195 if len(s.curPath) == 0 {
196 s.curPath.push(&pathStep{typ: t})
197 defer s.curPath.pop()
198 }
199 vx, vy = s.tryExporting(vx, vy)
200
201 // Rule 1: Check whether an option applies on this node in the value tree.
202 if s.tryOptions(vx, vy, t) {
203 return
204 }
205
206 // Rule 2: Check whether the type has a valid Equal method.
207 if s.tryMethod(vx, vy, t) {
208 return
209 }
210
211 // Rule 3: Recursively descend into each value's underlying kind.
212 switch t.Kind() {
213 case reflect.Bool:
214 s.report(vx.Bool() == vy.Bool(), vx, vy)
215 return
216 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
217 s.report(vx.Int() == vy.Int(), vx, vy)
218 return
219 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
220 s.report(vx.Uint() == vy.Uint(), vx, vy)
221 return
222 case reflect.Float32, reflect.Float64:
223 s.report(vx.Float() == vy.Float(), vx, vy)
224 return
225 case reflect.Complex64, reflect.Complex128:
226 s.report(vx.Complex() == vy.Complex(), vx, vy)
227 return
228 case reflect.String:
229 s.report(vx.String() == vy.String(), vx, vy)
230 return
231 case reflect.Chan, reflect.UnsafePointer:
232 s.report(vx.Pointer() == vy.Pointer(), vx, vy)
233 return
234 case reflect.Func:
235 s.report(vx.IsNil() && vy.IsNil(), vx, vy)
236 return
237 case reflect.Ptr:
238 if vx.IsNil() || vy.IsNil() {
239 s.report(vx.IsNil() && vy.IsNil(), vx, vy)
240 return
241 }
242 s.curPath.push(&indirect{pathStep{t.Elem()}})
243 defer s.curPath.pop()
244 s.compareAny(vx.Elem(), vy.Elem())
245 return
246 case reflect.Interface:
247 if vx.IsNil() || vy.IsNil() {
248 s.report(vx.IsNil() && vy.IsNil(), vx, vy)
249 return
250 }
251 if vx.Elem().Type() != vy.Elem().Type() {
252 s.report(false, vx.Elem(), vy.Elem())
253 return
254 }
255 s.curPath.push(&typeAssertion{pathStep{vx.Elem().Type()}})
256 defer s.curPath.pop()
257 s.compareAny(vx.Elem(), vy.Elem())
258 return
259 case reflect.Slice:
260 if vx.IsNil() || vy.IsNil() {
261 s.report(vx.IsNil() && vy.IsNil(), vx, vy)
262 return
263 }
264 fallthrough
265 case reflect.Array:
266 s.compareArray(vx, vy, t)
267 return
268 case reflect.Map:
269 s.compareMap(vx, vy, t)
270 return
271 case reflect.Struct:
272 s.compareStruct(vx, vy, t)
273 return
274 default:
275 panic(fmt.Sprintf("%v kind not handled", t.Kind()))
276 }
277}
278
279func (s *state) tryExporting(vx, vy reflect.Value) (reflect.Value, reflect.Value) {
280 if sf, ok := s.curPath[len(s.curPath)-1].(*structField); ok && sf.unexported {
281 if sf.force {
282 // Use unsafe pointer arithmetic to get read-write access to an
283 // unexported field in the struct.
284 vx = unsafeRetrieveField(sf.pvx, sf.field)
285 vy = unsafeRetrieveField(sf.pvy, sf.field)
286 } else {
287 // We are not allowed to export the value, so invalidate them
288 // so that tryOptions can panic later if not explicitly ignored.
289 vx = nothing
290 vy = nothing
291 }
292 }
293 return vx, vy
294}
295
296func (s *state) tryOptions(vx, vy reflect.Value, t reflect.Type) bool {
297 // If there were no FilterValues, we will not detect invalid inputs,
298 // so manually check for them and append invalid if necessary.
299 // We still evaluate the options since an ignore can override invalid.
300 opts := s.opts
301 if !vx.IsValid() || !vy.IsValid() {
302 opts = Options{opts, invalid{}}
303 }
304
305 // Evaluate all filters and apply the remaining options.
306 if opt := opts.filter(s, vx, vy, t); opt != nil {
307 opt.apply(s, vx, vy)
308 return true
309 }
310 return false
311}
312
313func (s *state) tryMethod(vx, vy reflect.Value, t reflect.Type) bool {
314 // Check if this type even has an Equal method.
315 m, ok := t.MethodByName("Equal")
316 if !ok || !function.IsType(m.Type, function.EqualAssignable) {
317 return false
318 }
319
320 eq := s.callTTBFunc(m.Func, vx, vy)
321 s.report(eq, vx, vy)
322 return true
323}
324
325func (s *state) callTRFunc(f, v reflect.Value) reflect.Value {
326 v = sanitizeValue(v, f.Type().In(0))
327 if !s.dynChecker.Next() {
328 return f.Call([]reflect.Value{v})[0]
329 }
330
331 // Run the function twice and ensure that we get the same results back.
332 // We run in goroutines so that the race detector (if enabled) can detect
333 // unsafe mutations to the input.
334 c := make(chan reflect.Value)
335 go detectRaces(c, f, v)
336 want := f.Call([]reflect.Value{v})[0]
337 if got := <-c; !s.statelessCompare(got, want).Equal() {
338 // To avoid false-positives with non-reflexive equality operations,
339 // we sanity check whether a value is equal to itself.
340 if !s.statelessCompare(want, want).Equal() {
341 return want
342 }
343 fn := getFuncName(f.Pointer())
344 panic(fmt.Sprintf("non-deterministic function detected: %s", fn))
345 }
346 return want
347}
348
349func (s *state) callTTBFunc(f, x, y reflect.Value) bool {
350 x = sanitizeValue(x, f.Type().In(0))
351 y = sanitizeValue(y, f.Type().In(1))
352 if !s.dynChecker.Next() {
353 return f.Call([]reflect.Value{x, y})[0].Bool()
354 }
355
356 // Swapping the input arguments is sufficient to check that
357 // f is symmetric and deterministic.
358 // We run in goroutines so that the race detector (if enabled) can detect
359 // unsafe mutations to the input.
360 c := make(chan reflect.Value)
361 go detectRaces(c, f, y, x)
362 want := f.Call([]reflect.Value{x, y})[0].Bool()
363 if got := <-c; !got.IsValid() || got.Bool() != want {
364 fn := getFuncName(f.Pointer())
365 panic(fmt.Sprintf("non-deterministic or non-symmetric function detected: %s", fn))
366 }
367 return want
368}
369
370func detectRaces(c chan<- reflect.Value, f reflect.Value, vs ...reflect.Value) {
371 var ret reflect.Value
372 defer func() {
373 recover() // Ignore panics, let the other call to f panic instead
374 c <- ret
375 }()
376 ret = f.Call(vs)[0]
377}
378
379// sanitizeValue converts nil interfaces of type T to those of type R,
380// assuming that T is assignable to R.
381// Otherwise, it returns the input value as is.
382func sanitizeValue(v reflect.Value, t reflect.Type) reflect.Value {
383 // TODO(dsnet): Remove this hacky workaround.
384 // See https://golang.org/issue/22143
385 if v.Kind() == reflect.Interface && v.IsNil() && v.Type() != t {
386 return reflect.New(t).Elem()
387 }
388 return v
389}
390
391func (s *state) compareArray(vx, vy reflect.Value, t reflect.Type) {
392 step := &sliceIndex{pathStep{t.Elem()}, 0, 0}
393 s.curPath.push(step)
394
395 // Compute an edit-script for slices vx and vy.
396 es := diff.Difference(vx.Len(), vy.Len(), func(ix, iy int) diff.Result {
397 step.xkey, step.ykey = ix, iy
398 return s.statelessCompare(vx.Index(ix), vy.Index(iy))
399 })
400
401 // Report the entire slice as is if the arrays are of primitive kind,
402 // and the arrays are different enough.
403 isPrimitive := false
404 switch t.Elem().Kind() {
405 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
406 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
407 reflect.Bool, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
408 isPrimitive = true
409 }
410 if isPrimitive && es.Dist() > (vx.Len()+vy.Len())/4 {
411 s.curPath.pop() // Pop first since we are reporting the whole slice
412 s.report(false, vx, vy)
413 return
414 }
415
416 // Replay the edit-script.
417 var ix, iy int
418 for _, e := range es {
419 switch e {
420 case diff.UniqueX:
421 step.xkey, step.ykey = ix, -1
422 s.report(false, vx.Index(ix), nothing)
423 ix++
424 case diff.UniqueY:
425 step.xkey, step.ykey = -1, iy
426 s.report(false, nothing, vy.Index(iy))
427 iy++
428 default:
429 step.xkey, step.ykey = ix, iy
430 if e == diff.Identity {
431 s.report(true, vx.Index(ix), vy.Index(iy))
432 } else {
433 s.compareAny(vx.Index(ix), vy.Index(iy))
434 }
435 ix++
436 iy++
437 }
438 }
439 s.curPath.pop()
440 return
441}
442
443func (s *state) compareMap(vx, vy reflect.Value, t reflect.Type) {
444 if vx.IsNil() || vy.IsNil() {
445 s.report(vx.IsNil() && vy.IsNil(), vx, vy)
446 return
447 }
448
449 // We combine and sort the two map keys so that we can perform the
450 // comparisons in a deterministic order.
451 step := &mapIndex{pathStep: pathStep{t.Elem()}}
452 s.curPath.push(step)
453 defer s.curPath.pop()
454 for _, k := range value.SortKeys(append(vx.MapKeys(), vy.MapKeys()...)) {
455 step.key = k
456 vvx := vx.MapIndex(k)
457 vvy := vy.MapIndex(k)
458 switch {
459 case vvx.IsValid() && vvy.IsValid():
460 s.compareAny(vvx, vvy)
461 case vvx.IsValid() && !vvy.IsValid():
462 s.report(false, vvx, nothing)
463 case !vvx.IsValid() && vvy.IsValid():
464 s.report(false, nothing, vvy)
465 default:
466 // It is possible for both vvx and vvy to be invalid if the
467 // key contained a NaN value in it. There is no way in
468 // reflection to be able to retrieve these values.
469 // See https://golang.org/issue/11104
470 panic(fmt.Sprintf("%#v has map key with NaNs", s.curPath))
471 }
472 }
473}
474
475func (s *state) compareStruct(vx, vy reflect.Value, t reflect.Type) {
476 var vax, vay reflect.Value // Addressable versions of vx and vy
477
478 step := &structField{}
479 s.curPath.push(step)
480 defer s.curPath.pop()
481 for i := 0; i < t.NumField(); i++ {
482 vvx := vx.Field(i)
483 vvy := vy.Field(i)
484 step.typ = t.Field(i).Type
485 step.name = t.Field(i).Name
486 step.idx = i
487 step.unexported = !isExported(step.name)
488 if step.unexported {
489 // Defer checking of unexported fields until later to give an
490 // Ignore a chance to ignore the field.
491 if !vax.IsValid() || !vay.IsValid() {
492 // For unsafeRetrieveField to work, the parent struct must
493 // be addressable. Create a new copy of the values if
494 // necessary to make them addressable.
495 vax = makeAddressable(vx)
496 vay = makeAddressable(vy)
497 }
498 step.force = s.exporters[t]
499 step.pvx = vax
500 step.pvy = vay
501 step.field = t.Field(i)
502 }
503 s.compareAny(vvx, vvy)
504 }
505}
506
507// report records the result of a single comparison.
508// It also calls Report if any reporter is registered.
509func (s *state) report(eq bool, vx, vy reflect.Value) {
510 if eq {
511 s.result.NSame++
512 } else {
513 s.result.NDiff++
514 }
515 if s.reporter != nil {
516 s.reporter.Report(vx, vy, eq, s.curPath)
517 }
518}
519
520// dynChecker tracks the state needed to periodically perform checks that
521// user provided functions are symmetric and deterministic.
522// The zero value is safe for immediate use.
523type dynChecker struct{ curr, next int }
524
525// Next increments the state and reports whether a check should be performed.
526//
527// Checks occur every Nth function call, where N is a triangular number:
528// 0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 ...
529// See https://en.wikipedia.org/wiki/Triangular_number
530//
531// This sequence ensures that the cost of checks drops significantly as
532// the number of functions calls grows larger.
533func (dc *dynChecker) Next() bool {
534 ok := dc.curr == dc.next
535 if ok {
536 dc.curr = 0
537 dc.next++
538 }
539 dc.curr++
540 return ok
541}
542
543// makeAddressable returns a value that is always addressable.
544// It returns the input verbatim if it is already addressable,
545// otherwise it creates a new value and returns an addressable copy.
546func makeAddressable(v reflect.Value) reflect.Value {
547 if v.CanAddr() {
548 return v
549 }
550 vc := reflect.New(v.Type()).Elem()
551 vc.Set(v)
552 return vc
553}
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go
new file mode 100644
index 0000000..42afa49
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go
@@ -0,0 +1,17 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// +build !debug
6
7package diff
8
9var debug debugger
10
11type debugger struct{}
12
13func (debugger) Begin(_, _ int, f EqualFunc, _, _ *EditScript) EqualFunc {
14 return f
15}
16func (debugger) Update() {}
17func (debugger) Finish() {}
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go
new file mode 100644
index 0000000..fd9f7f1
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go
@@ -0,0 +1,122 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// +build debug
6
7package diff
8
9import (
10 "fmt"
11 "strings"
12 "sync"
13 "time"
14)
15
16// The algorithm can be seen running in real-time by enabling debugging:
17// go test -tags=debug -v
18//
19// Example output:
20// === RUN TestDifference/#34
21// ┌───────────────────────────────┐
22// │ \ · · · · · · · · · · · · · · │
23// │ · # · · · · · · · · · · · · · │
24// │ · \ · · · · · · · · · · · · · │
25// │ · · \ · · · · · · · · · · · · │
26// │ · · · X # · · · · · · · · · · │
27// │ · · · # \ · · · · · · · · · · │
28// │ · · · · · # # · · · · · · · · │
29// │ · · · · · # \ · · · · · · · · │
30// │ · · · · · · · \ · · · · · · · │
31// │ · · · · · · · · \ · · · · · · │
32// │ · · · · · · · · · \ · · · · · │
33// │ · · · · · · · · · · \ · · # · │
34// │ · · · · · · · · · · · \ # # · │
35// │ · · · · · · · · · · · # # # · │
36// │ · · · · · · · · · · # # # # · │
37// │ · · · · · · · · · # # # # # · │
38// │ · · · · · · · · · · · · · · \ │
39// └───────────────────────────────┘
40// [.Y..M.XY......YXYXY.|]
41//
42// The grid represents the edit-graph where the horizontal axis represents
43// list X and the vertical axis represents list Y. The start of the two lists
44// is the top-left, while the ends are the bottom-right. The '·' represents
45// an unexplored node in the graph. The '\' indicates that the two symbols
46// from list X and Y are equal. The 'X' indicates that two symbols are similar
47// (but not exactly equal) to each other. The '#' indicates that the two symbols
48// are different (and not similar). The algorithm traverses this graph trying to
49// make the paths starting in the top-left and the bottom-right connect.
50//
51// The series of '.', 'X', 'Y', and 'M' characters at the bottom represents
52// the currently established path from the forward and reverse searches,
53// separated by a '|' character.
54
55const (
56 updateDelay = 100 * time.Millisecond
57 finishDelay = 500 * time.Millisecond
58 ansiTerminal = true // ANSI escape codes used to move terminal cursor
59)
60
61var debug debugger
62
63type debugger struct {
64 sync.Mutex
65 p1, p2 EditScript
66 fwdPath, revPath *EditScript
67 grid []byte
68 lines int
69}
70
71func (dbg *debugger) Begin(nx, ny int, f EqualFunc, p1, p2 *EditScript) EqualFunc {
72 dbg.Lock()
73 dbg.fwdPath, dbg.revPath = p1, p2
74 top := "┌─" + strings.Repeat("──", nx) + "┐\n"
75 row := "│ " + strings.Repeat("· ", nx) + "│\n"
76 btm := "└─" + strings.Repeat("──", nx) + "┘\n"
77 dbg.grid = []byte(top + strings.Repeat(row, ny) + btm)
78 dbg.lines = strings.Count(dbg.String(), "\n")
79 fmt.Print(dbg)
80
81 // Wrap the EqualFunc so that we can intercept each result.
82 return func(ix, iy int) (r Result) {
83 cell := dbg.grid[len(top)+iy*len(row):][len("│ ")+len("· ")*ix:][:len("·")]
84 for i := range cell {
85 cell[i] = 0 // Zero out the multiple bytes of UTF-8 middle-dot
86 }
87 switch r = f(ix, iy); {
88 case r.Equal():
89 cell[0] = '\\'
90 case r.Similar():
91 cell[0] = 'X'
92 default:
93 cell[0] = '#'
94 }
95 return
96 }
97}
98
99func (dbg *debugger) Update() {
100 dbg.print(updateDelay)
101}
102
103func (dbg *debugger) Finish() {
104 dbg.print(finishDelay)
105 dbg.Unlock()
106}
107
108func (dbg *debugger) String() string {
109 dbg.p1, dbg.p2 = *dbg.fwdPath, dbg.p2[:0]
110 for i := len(*dbg.revPath) - 1; i >= 0; i-- {
111 dbg.p2 = append(dbg.p2, (*dbg.revPath)[i])
112 }
113 return fmt.Sprintf("%s[%v|%v]\n\n", dbg.grid, dbg.p1, dbg.p2)
114}
115
116func (dbg *debugger) print(d time.Duration) {
117 if ansiTerminal {
118 fmt.Printf("\x1b[%dA", dbg.lines) // Reset terminal cursor
119 }
120 fmt.Print(dbg)
121 time.Sleep(d)
122}
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go
new file mode 100644
index 0000000..260befe
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go
@@ -0,0 +1,363 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// Package diff implements an algorithm for producing edit-scripts.
6// The edit-script is a sequence of operations needed to transform one list
7// of symbols into another (or vice-versa). The edits allowed are insertions,
8// deletions, and modifications. The summation of all edits is called the
9// Levenshtein distance as this problem is well-known in computer science.
10//
11// This package prioritizes performance over accuracy. That is, the run time
12// is more important than obtaining a minimal Levenshtein distance.
13package diff
14
15// EditType represents a single operation within an edit-script.
16type EditType uint8
17
18const (
19 // Identity indicates that a symbol pair is identical in both list X and Y.
20 Identity EditType = iota
21 // UniqueX indicates that a symbol only exists in X and not Y.
22 UniqueX
23 // UniqueY indicates that a symbol only exists in Y and not X.
24 UniqueY
25 // Modified indicates that a symbol pair is a modification of each other.
26 Modified
27)
28
29// EditScript represents the series of differences between two lists.
30type EditScript []EditType
31
32// String returns a human-readable string representing the edit-script where
33// Identity, UniqueX, UniqueY, and Modified are represented by the
34// '.', 'X', 'Y', and 'M' characters, respectively.
35func (es EditScript) String() string {
36 b := make([]byte, len(es))
37 for i, e := range es {
38 switch e {
39 case Identity:
40 b[i] = '.'
41 case UniqueX:
42 b[i] = 'X'
43 case UniqueY:
44 b[i] = 'Y'
45 case Modified:
46 b[i] = 'M'
47 default:
48 panic("invalid edit-type")
49 }
50 }
51 return string(b)
52}
53
54// stats returns a histogram of the number of each type of edit operation.
55func (es EditScript) stats() (s struct{ NI, NX, NY, NM int }) {
56 for _, e := range es {
57 switch e {
58 case Identity:
59 s.NI++
60 case UniqueX:
61 s.NX++
62 case UniqueY:
63 s.NY++
64 case Modified:
65 s.NM++
66 default:
67 panic("invalid edit-type")
68 }
69 }
70 return
71}
72
73// Dist is the Levenshtein distance and is guaranteed to be 0 if and only if
74// lists X and Y are equal.
75func (es EditScript) Dist() int { return len(es) - es.stats().NI }
76
77// LenX is the length of the X list.
78func (es EditScript) LenX() int { return len(es) - es.stats().NY }
79
80// LenY is the length of the Y list.
81func (es EditScript) LenY() int { return len(es) - es.stats().NX }
82
83// EqualFunc reports whether the symbols at indexes ix and iy are equal.
84// When called by Difference, the index is guaranteed to be within nx and ny.
85type EqualFunc func(ix int, iy int) Result
86
87// Result is the result of comparison.
88// NSame is the number of sub-elements that are equal.
89// NDiff is the number of sub-elements that are not equal.
90type Result struct{ NSame, NDiff int }
91
92// Equal indicates whether the symbols are equal. Two symbols are equal
93// if and only if NDiff == 0. If Equal, then they are also Similar.
94func (r Result) Equal() bool { return r.NDiff == 0 }
95
96// Similar indicates whether two symbols are similar and may be represented
97// by using the Modified type. As a special case, we consider binary comparisons
98// (i.e., those that return Result{1, 0} or Result{0, 1}) to be similar.
99//
100// The exact ratio of NSame to NDiff to determine similarity may change.
101func (r Result) Similar() bool {
102 // Use NSame+1 to offset NSame so that binary comparisons are similar.
103 return r.NSame+1 >= r.NDiff
104}
105
106// Difference reports whether two lists of lengths nx and ny are equal
107// given the definition of equality provided as f.
108//
109// This function returns an edit-script, which is a sequence of operations
110// needed to convert one list into the other. The following invariants for
111// the edit-script are maintained:
112// • eq == (es.Dist()==0)
113// • nx == es.LenX()
114// • ny == es.LenY()
115//
116// This algorithm is not guaranteed to be an optimal solution (i.e., one that
117// produces an edit-script with a minimal Levenshtein distance). This algorithm
118// favors performance over optimality. The exact output is not guaranteed to
119// be stable and may change over time.
120func Difference(nx, ny int, f EqualFunc) (es EditScript) {
121 // This algorithm is based on traversing what is known as an "edit-graph".
122 // See Figure 1 from "An O(ND) Difference Algorithm and Its Variations"
123 // by Eugene W. Myers. Since D can be as large as N itself, this is
124 // effectively O(N^2). Unlike the algorithm from that paper, we are not
125 // interested in the optimal path, but at least some "decent" path.
126 //
127 // For example, let X and Y be lists of symbols:
128 // X = [A B C A B B A]
129 // Y = [C B A B A C]
130 //
131 // The edit-graph can be drawn as the following:
132 // A B C A B B A
133 // ┌─────────────┐
134 // C │_|_|\|_|_|_|_│ 0
135 // B │_|\|_|_|\|\|_│ 1
136 // A │\|_|_|\|_|_|\│ 2
137 // B │_|\|_|_|\|\|_│ 3
138 // A │\|_|_|\|_|_|\│ 4
139 // C │ | |\| | | | │ 5
140 // └─────────────┘ 6
141 // 0 1 2 3 4 5 6 7
142 //
143 // List X is written along the horizontal axis, while list Y is written
144 // along the vertical axis. At any point on this grid, if the symbol in
145 // list X matches the corresponding symbol in list Y, then a '\' is drawn.
146 // The goal of any minimal edit-script algorithm is to find a path from the
147 // top-left corner to the bottom-right corner, while traveling through the
148 // fewest horizontal or vertical edges.
149 // A horizontal edge is equivalent to inserting a symbol from list X.
150 // A vertical edge is equivalent to inserting a symbol from list Y.
151 // A diagonal edge is equivalent to a matching symbol between both X and Y.
152
153 // Invariants:
154 // • 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx
155 // • 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny
156 //
157 // In general:
158 // • fwdFrontier.X < revFrontier.X
159 // • fwdFrontier.Y < revFrontier.Y
160 // Unless, it is time for the algorithm to terminate.
161 fwdPath := path{+1, point{0, 0}, make(EditScript, 0, (nx+ny)/2)}
162 revPath := path{-1, point{nx, ny}, make(EditScript, 0)}
163 fwdFrontier := fwdPath.point // Forward search frontier
164 revFrontier := revPath.point // Reverse search frontier
165
166 // Search budget bounds the cost of searching for better paths.
167 // The longest sequence of non-matching symbols that can be tolerated is
168 // approximately the square-root of the search budget.
169 searchBudget := 4 * (nx + ny) // O(n)
170
171 // The algorithm below is a greedy, meet-in-the-middle algorithm for
172 // computing sub-optimal edit-scripts between two lists.
173 //
174 // The algorithm is approximately as follows:
175 // • Searching for differences switches back-and-forth between
176 // a search that starts at the beginning (the top-left corner), and
177 // a search that starts at the end (the bottom-right corner). The goal of
178 // the search is connect with the search from the opposite corner.
179 // • As we search, we build a path in a greedy manner, where the first
180 // match seen is added to the path (this is sub-optimal, but provides a
181 // decent result in practice). When matches are found, we try the next pair
182 // of symbols in the lists and follow all matches as far as possible.
183 // • When searching for matches, we search along a diagonal going through
184 // through the "frontier" point. If no matches are found, we advance the
185 // frontier towards the opposite corner.
186 // • This algorithm terminates when either the X coordinates or the
187 // Y coordinates of the forward and reverse frontier points ever intersect.
188 //
189 // This algorithm is correct even if searching only in the forward direction
190 // or in the reverse direction. We do both because it is commonly observed
191 // that two lists commonly differ because elements were added to the front
192 // or end of the other list.
193 //
194 // Running the tests with the "debug" build tag prints a visualization of
195 // the algorithm running in real-time. This is educational for understanding
196 // how the algorithm works. See debug_enable.go.
197 f = debug.Begin(nx, ny, f, &fwdPath.es, &revPath.es)
198 for {
199 // Forward search from the beginning.
200 if fwdFrontier.X >= revFrontier.X || fwdFrontier.Y >= revFrontier.Y || searchBudget == 0 {
201 break
202 }
203 for stop1, stop2, i := false, false, 0; !(stop1 && stop2) && searchBudget > 0; i++ {
204 // Search in a diagonal pattern for a match.
205 z := zigzag(i)
206 p := point{fwdFrontier.X + z, fwdFrontier.Y - z}
207 switch {
208 case p.X >= revPath.X || p.Y < fwdPath.Y:
209 stop1 = true // Hit top-right corner
210 case p.Y >= revPath.Y || p.X < fwdPath.X:
211 stop2 = true // Hit bottom-left corner
212 case f(p.X, p.Y).Equal():
213 // Match found, so connect the path to this point.
214 fwdPath.connect(p, f)
215 fwdPath.append(Identity)
216 // Follow sequence of matches as far as possible.
217 for fwdPath.X < revPath.X && fwdPath.Y < revPath.Y {
218 if !f(fwdPath.X, fwdPath.Y).Equal() {
219 break
220 }
221 fwdPath.append(Identity)
222 }
223 fwdFrontier = fwdPath.point
224 stop1, stop2 = true, true
225 default:
226 searchBudget-- // Match not found
227 }
228 debug.Update()
229 }
230 // Advance the frontier towards reverse point.
231 if revPath.X-fwdFrontier.X >= revPath.Y-fwdFrontier.Y {
232 fwdFrontier.X++
233 } else {
234 fwdFrontier.Y++
235 }
236
237 // Reverse search from the end.
238 if fwdFrontier.X >= revFrontier.X || fwdFrontier.Y >= revFrontier.Y || searchBudget == 0 {
239 break
240 }
241 for stop1, stop2, i := false, false, 0; !(stop1 && stop2) && searchBudget > 0; i++ {
242 // Search in a diagonal pattern for a match.
243 z := zigzag(i)
244 p := point{revFrontier.X - z, revFrontier.Y + z}
245 switch {
246 case fwdPath.X >= p.X || revPath.Y < p.Y:
247 stop1 = true // Hit bottom-left corner
248 case fwdPath.Y >= p.Y || revPath.X < p.X:
249 stop2 = true // Hit top-right corner
250 case f(p.X-1, p.Y-1).Equal():
251 // Match found, so connect the path to this point.
252 revPath.connect(p, f)
253 revPath.append(Identity)
254 // Follow sequence of matches as far as possible.
255 for fwdPath.X < revPath.X && fwdPath.Y < revPath.Y {
256 if !f(revPath.X-1, revPath.Y-1).Equal() {
257 break
258 }
259 revPath.append(Identity)
260 }
261 revFrontier = revPath.point
262 stop1, stop2 = true, true
263 default:
264 searchBudget-- // Match not found
265 }
266 debug.Update()
267 }
268 // Advance the frontier towards forward point.
269 if revFrontier.X-fwdPath.X >= revFrontier.Y-fwdPath.Y {
270 revFrontier.X--
271 } else {
272 revFrontier.Y--
273 }
274 }
275
276 // Join the forward and reverse paths and then append the reverse path.
277 fwdPath.connect(revPath.point, f)
278 for i := len(revPath.es) - 1; i >= 0; i-- {
279 t := revPath.es[i]
280 revPath.es = revPath.es[:i]
281 fwdPath.append(t)
282 }
283 debug.Finish()
284 return fwdPath.es
285}
286
287type path struct {
288 dir int // +1 if forward, -1 if reverse
289 point // Leading point of the EditScript path
290 es EditScript
291}
292
293// connect appends any necessary Identity, Modified, UniqueX, or UniqueY types
294// to the edit-script to connect p.point to dst.
295func (p *path) connect(dst point, f EqualFunc) {
296 if p.dir > 0 {
297 // Connect in forward direction.
298 for dst.X > p.X && dst.Y > p.Y {
299 switch r := f(p.X, p.Y); {
300 case r.Equal():
301 p.append(Identity)
302 case r.Similar():
303 p.append(Modified)
304 case dst.X-p.X >= dst.Y-p.Y:
305 p.append(UniqueX)
306 default:
307 p.append(UniqueY)
308 }
309 }
310 for dst.X > p.X {
311 p.append(UniqueX)
312 }
313 for dst.Y > p.Y {
314 p.append(UniqueY)
315 }
316 } else {
317 // Connect in reverse direction.
318 for p.X > dst.X && p.Y > dst.Y {
319 switch r := f(p.X-1, p.Y-1); {
320 case r.Equal():
321 p.append(Identity)
322 case r.Similar():
323 p.append(Modified)
324 case p.Y-dst.Y >= p.X-dst.X:
325 p.append(UniqueY)
326 default:
327 p.append(UniqueX)
328 }
329 }
330 for p.X > dst.X {
331 p.append(UniqueX)
332 }
333 for p.Y > dst.Y {
334 p.append(UniqueY)
335 }
336 }
337}
338
339func (p *path) append(t EditType) {
340 p.es = append(p.es, t)
341 switch t {
342 case Identity, Modified:
343 p.add(p.dir, p.dir)
344 case UniqueX:
345 p.add(p.dir, 0)
346 case UniqueY:
347 p.add(0, p.dir)
348 }
349 debug.Update()
350}
351
352type point struct{ X, Y int }
353
354func (p *point) add(dx, dy int) { p.X += dx; p.Y += dy }
355
356// zigzag maps a consecutive sequence of integers to a zig-zag sequence.
357// [0 1 2 3 4 5 ...] => [0 -1 +1 -2 +2 ...]
358func zigzag(x int) int {
359 if x&1 != 0 {
360 x = ^x
361 }
362 return x >> 1
363}
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/function/func.go b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go
new file mode 100644
index 0000000..4c35ff1
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go
@@ -0,0 +1,49 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// Package function identifies function types.
6package function
7
8import "reflect"
9
10type funcType int
11
12const (
13 _ funcType = iota
14
15 ttbFunc // func(T, T) bool
16 tibFunc // func(T, I) bool
17 trFunc // func(T) R
18
19 Equal = ttbFunc // func(T, T) bool
20 EqualAssignable = tibFunc // func(T, I) bool; encapsulates func(T, T) bool
21 Transformer = trFunc // func(T) R
22 ValueFilter = ttbFunc // func(T, T) bool
23 Less = ttbFunc // func(T, T) bool
24)
25
26var boolType = reflect.TypeOf(true)
27
28// IsType reports whether the reflect.Type is of the specified function type.
29func IsType(t reflect.Type, ft funcType) bool {
30 if t == nil || t.Kind() != reflect.Func || t.IsVariadic() {
31 return false
32 }
33 ni, no := t.NumIn(), t.NumOut()
34 switch ft {
35 case ttbFunc: // func(T, T) bool
36 if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == boolType {
37 return true
38 }
39 case tibFunc: // func(T, I) bool
40 if ni == 2 && no == 1 && t.In(0).AssignableTo(t.In(1)) && t.Out(0) == boolType {
41 return true
42 }
43 case trFunc: // func(T) R
44 if ni == 1 && no == 1 {
45 return true
46 }
47 }
48 return false
49}
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/format.go b/vendor/github.com/google/go-cmp/cmp/internal/value/format.go
new file mode 100644
index 0000000..657e508
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/internal/value/format.go
@@ -0,0 +1,277 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// Package value provides functionality for reflect.Value types.
6package value
7
8import (
9 "fmt"
10 "reflect"
11 "strconv"
12 "strings"
13 "unicode"
14)
15
16var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
17
18// Format formats the value v as a string.
19//
20// This is similar to fmt.Sprintf("%+v", v) except this:
21// * Prints the type unless it can be elided
22// * Avoids printing struct fields that are zero
23// * Prints a nil-slice as being nil, not empty
24// * Prints map entries in deterministic order
25func Format(v reflect.Value, conf FormatConfig) string {
26 conf.printType = true
27 conf.followPointers = true
28 conf.realPointers = true
29 return formatAny(v, conf, nil)
30}
31
32type FormatConfig struct {
33 UseStringer bool // Should the String method be used if available?
34 printType bool // Should we print the type before the value?
35 PrintPrimitiveType bool // Should we print the type of primitives?
36 followPointers bool // Should we recursively follow pointers?
37 realPointers bool // Should we print the real address of pointers?
38}
39
40func formatAny(v reflect.Value, conf FormatConfig, visited map[uintptr]bool) string {
41 // TODO: Should this be a multi-line printout in certain situations?
42
43 if !v.IsValid() {
44 return "<non-existent>"
45 }
46 if conf.UseStringer && v.Type().Implements(stringerIface) && v.CanInterface() {
47 if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() {
48 return "<nil>"
49 }
50
51 const stringerPrefix = "s" // Indicates that the String method was used
52 s := v.Interface().(fmt.Stringer).String()
53 return stringerPrefix + formatString(s)
54 }
55
56 switch v.Kind() {
57 case reflect.Bool:
58 return formatPrimitive(v.Type(), v.Bool(), conf)
59 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
60 return formatPrimitive(v.Type(), v.Int(), conf)
61 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
62 if v.Type().PkgPath() == "" || v.Kind() == reflect.Uintptr {
63 // Unnamed uints are usually bytes or words, so use hexadecimal.
64 return formatPrimitive(v.Type(), formatHex(v.Uint()), conf)
65 }
66 return formatPrimitive(v.Type(), v.Uint(), conf)
67 case reflect.Float32, reflect.Float64:
68 return formatPrimitive(v.Type(), v.Float(), conf)
69 case reflect.Complex64, reflect.Complex128:
70 return formatPrimitive(v.Type(), v.Complex(), conf)
71 case reflect.String:
72 return formatPrimitive(v.Type(), formatString(v.String()), conf)
73 case reflect.UnsafePointer, reflect.Chan, reflect.Func:
74 return formatPointer(v, conf)
75 case reflect.Ptr:
76 if v.IsNil() {
77 if conf.printType {
78 return fmt.Sprintf("(%v)(nil)", v.Type())
79 }
80 return "<nil>"
81 }
82 if visited[v.Pointer()] || !conf.followPointers {
83 return formatPointer(v, conf)
84 }
85 visited = insertPointer(visited, v.Pointer())
86 return "&" + formatAny(v.Elem(), conf, visited)
87 case reflect.Interface:
88 if v.IsNil() {
89 if conf.printType {
90 return fmt.Sprintf("%v(nil)", v.Type())
91 }
92 return "<nil>"
93 }
94 return formatAny(v.Elem(), conf, visited)
95 case reflect.Slice:
96 if v.IsNil() {
97 if conf.printType {
98 return fmt.Sprintf("%v(nil)", v.Type())
99 }
100 return "<nil>"
101 }
102 if visited[v.Pointer()] {
103 return formatPointer(v, conf)
104 }
105 visited = insertPointer(visited, v.Pointer())
106 fallthrough
107 case reflect.Array:
108 var ss []string
109 subConf := conf
110 subConf.printType = v.Type().Elem().Kind() == reflect.Interface
111 for i := 0; i < v.Len(); i++ {
112 s := formatAny(v.Index(i), subConf, visited)
113 ss = append(ss, s)
114 }
115 s := fmt.Sprintf("{%s}", strings.Join(ss, ", "))
116 if conf.printType {
117 return v.Type().String() + s
118 }
119 return s
120 case reflect.Map:
121 if v.IsNil() {
122 if conf.printType {
123 return fmt.Sprintf("%v(nil)", v.Type())
124 }
125 return "<nil>"
126 }
127 if visited[v.Pointer()] {
128 return formatPointer(v, conf)
129 }
130 visited = insertPointer(visited, v.Pointer())
131
132 var ss []string
133 keyConf, valConf := conf, conf
134 keyConf.printType = v.Type().Key().Kind() == reflect.Interface
135 keyConf.followPointers = false
136 valConf.printType = v.Type().Elem().Kind() == reflect.Interface
137 for _, k := range SortKeys(v.MapKeys()) {
138 sk := formatAny(k, keyConf, visited)
139 sv := formatAny(v.MapIndex(k), valConf, visited)
140 ss = append(ss, fmt.Sprintf("%s: %s", sk, sv))
141 }
142 s := fmt.Sprintf("{%s}", strings.Join(ss, ", "))
143 if conf.printType {
144 return v.Type().String() + s
145 }
146 return s
147 case reflect.Struct:
148 var ss []string
149 subConf := conf
150 subConf.printType = true
151 for i := 0; i < v.NumField(); i++ {
152 vv := v.Field(i)
153 if isZero(vv) {
154 continue // Elide zero value fields
155 }
156 name := v.Type().Field(i).Name
157 subConf.UseStringer = conf.UseStringer
158 s := formatAny(vv, subConf, visited)
159 ss = append(ss, fmt.Sprintf("%s: %s", name, s))
160 }
161 s := fmt.Sprintf("{%s}", strings.Join(ss, ", "))
162 if conf.printType {
163 return v.Type().String() + s
164 }
165 return s
166 default:
167 panic(fmt.Sprintf("%v kind not handled", v.Kind()))
168 }
169}
170
171func formatString(s string) string {
172 // Use quoted string if it the same length as a raw string literal.
173 // Otherwise, attempt to use the raw string form.
174 qs := strconv.Quote(s)
175 if len(qs) == 1+len(s)+1 {
176 return qs
177 }
178
179 // Disallow newlines to ensure output is a single line.
180 // Only allow printable runes for readability purposes.
181 rawInvalid := func(r rune) bool {
182 return r == '`' || r == '\n' || !unicode.IsPrint(r)
183 }
184 if strings.IndexFunc(s, rawInvalid) < 0 {
185 return "`" + s + "`"
186 }
187 return qs
188}
189
190func formatPrimitive(t reflect.Type, v interface{}, conf FormatConfig) string {
191 if conf.printType && (conf.PrintPrimitiveType || t.PkgPath() != "") {
192 return fmt.Sprintf("%v(%v)", t, v)
193 }
194 return fmt.Sprintf("%v", v)
195}
196
197func formatPointer(v reflect.Value, conf FormatConfig) string {
198 p := v.Pointer()
199 if !conf.realPointers {
200 p = 0 // For deterministic printing purposes
201 }
202 s := formatHex(uint64(p))
203 if conf.printType {
204 return fmt.Sprintf("(%v)(%s)", v.Type(), s)
205 }
206 return s
207}
208
209func formatHex(u uint64) string {
210 var f string
211 switch {
212 case u <= 0xff:
213 f = "0x%02x"
214 case u <= 0xffff:
215 f = "0x%04x"
216 case u <= 0xffffff:
217 f = "0x%06x"
218 case u <= 0xffffffff:
219 f = "0x%08x"
220 case u <= 0xffffffffff:
221 f = "0x%010x"
222 case u <= 0xffffffffffff:
223 f = "0x%012x"
224 case u <= 0xffffffffffffff:
225 f = "0x%014x"
226 case u <= 0xffffffffffffffff:
227 f = "0x%016x"
228 }
229 return fmt.Sprintf(f, u)
230}
231
232// insertPointer insert p into m, allocating m if necessary.
233func insertPointer(m map[uintptr]bool, p uintptr) map[uintptr]bool {
234 if m == nil {
235 m = make(map[uintptr]bool)
236 }
237 m[p] = true
238 return m
239}
240
241// isZero reports whether v is the zero value.
242// This does not rely on Interface and so can be used on unexported fields.
243func isZero(v reflect.Value) bool {
244 switch v.Kind() {
245 case reflect.Bool:
246 return v.Bool() == false
247 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
248 return v.Int() == 0
249 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
250 return v.Uint() == 0
251 case reflect.Float32, reflect.Float64:
252 return v.Float() == 0
253 case reflect.Complex64, reflect.Complex128:
254 return v.Complex() == 0
255 case reflect.String:
256 return v.String() == ""
257 case reflect.UnsafePointer:
258 return v.Pointer() == 0
259 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
260 return v.IsNil()
261 case reflect.Array:
262 for i := 0; i < v.Len(); i++ {
263 if !isZero(v.Index(i)) {
264 return false
265 }
266 }
267 return true
268 case reflect.Struct:
269 for i := 0; i < v.NumField(); i++ {
270 if !isZero(v.Field(i)) {
271 return false
272 }
273 }
274 return true
275 }
276 return false
277}
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/sort.go b/vendor/github.com/google/go-cmp/cmp/internal/value/sort.go
new file mode 100644
index 0000000..fe8aa27
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/internal/value/sort.go
@@ -0,0 +1,111 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5package value
6
7import (
8 "fmt"
9 "math"
10 "reflect"
11 "sort"
12)
13
14// SortKeys sorts a list of map keys, deduplicating keys if necessary.
15// The type of each value must be comparable.
16func SortKeys(vs []reflect.Value) []reflect.Value {
17 if len(vs) == 0 {
18 return vs
19 }
20
21 // Sort the map keys.
22 sort.Sort(valueSorter(vs))
23
24 // Deduplicate keys (fails for NaNs).
25 vs2 := vs[:1]
26 for _, v := range vs[1:] {
27 if isLess(vs2[len(vs2)-1], v) {
28 vs2 = append(vs2, v)
29 }
30 }
31 return vs2
32}
33
34// TODO: Use sort.Slice once Google AppEngine is on Go1.8 or above.
35type valueSorter []reflect.Value
36
37func (vs valueSorter) Len() int { return len(vs) }
38func (vs valueSorter) Less(i, j int) bool { return isLess(vs[i], vs[j]) }
39func (vs valueSorter) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
40
41// isLess is a generic function for sorting arbitrary map keys.
42// The inputs must be of the same type and must be comparable.
43func isLess(x, y reflect.Value) bool {
44 switch x.Type().Kind() {
45 case reflect.Bool:
46 return !x.Bool() && y.Bool()
47 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
48 return x.Int() < y.Int()
49 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
50 return x.Uint() < y.Uint()
51 case reflect.Float32, reflect.Float64:
52 fx, fy := x.Float(), y.Float()
53 return fx < fy || math.IsNaN(fx) && !math.IsNaN(fy)
54 case reflect.Complex64, reflect.Complex128:
55 cx, cy := x.Complex(), y.Complex()
56 rx, ix, ry, iy := real(cx), imag(cx), real(cy), imag(cy)
57 if rx == ry || (math.IsNaN(rx) && math.IsNaN(ry)) {
58 return ix < iy || math.IsNaN(ix) && !math.IsNaN(iy)
59 }
60 return rx < ry || math.IsNaN(rx) && !math.IsNaN(ry)
61 case reflect.Ptr, reflect.UnsafePointer, reflect.Chan:
62 return x.Pointer() < y.Pointer()
63 case reflect.String:
64 return x.String() < y.String()
65 case reflect.Array:
66 for i := 0; i < x.Len(); i++ {
67 if isLess(x.Index(i), y.Index(i)) {
68 return true
69 }
70 if isLess(y.Index(i), x.Index(i)) {
71 return false
72 }
73 }
74 return false
75 case reflect.Struct:
76 for i := 0; i < x.NumField(); i++ {
77 if isLess(x.Field(i), y.Field(i)) {
78 return true
79 }
80 if isLess(y.Field(i), x.Field(i)) {
81 return false
82 }
83 }
84 return false
85 case reflect.Interface:
86 vx, vy := x.Elem(), y.Elem()
87 if !vx.IsValid() || !vy.IsValid() {
88 return !vx.IsValid() && vy.IsValid()
89 }
90 tx, ty := vx.Type(), vy.Type()
91 if tx == ty {
92 return isLess(x.Elem(), y.Elem())
93 }
94 if tx.Kind() != ty.Kind() {
95 return vx.Kind() < vy.Kind()
96 }
97 if tx.String() != ty.String() {
98 return tx.String() < ty.String()
99 }
100 if tx.PkgPath() != ty.PkgPath() {
101 return tx.PkgPath() < ty.PkgPath()
102 }
103 // This can happen in rare situations, so we fallback to just comparing
104 // the unique pointer for a reflect.Type. This guarantees deterministic
105 // ordering within a program, but it is obviously not stable.
106 return reflect.ValueOf(vx.Type()).Pointer() < reflect.ValueOf(vy.Type()).Pointer()
107 default:
108 // Must be Func, Map, or Slice; which are not comparable.
109 panic(fmt.Sprintf("%T is not comparable", x.Type()))
110 }
111}
diff --git a/vendor/github.com/google/go-cmp/cmp/options.go b/vendor/github.com/google/go-cmp/cmp/options.go
new file mode 100644
index 0000000..91d4b06
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/options.go
@@ -0,0 +1,453 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5package cmp
6
7import (
8 "fmt"
9 "reflect"
10 "runtime"
11 "strings"
12
13 "github.com/google/go-cmp/cmp/internal/function"
14)
15
16// Option configures for specific behavior of Equal and Diff. In particular,
17// the fundamental Option functions (Ignore, Transformer, and Comparer),
18// configure how equality is determined.
19//
20// The fundamental options may be composed with filters (FilterPath and
21// FilterValues) to control the scope over which they are applied.
22//
23// The cmp/cmpopts package provides helper functions for creating options that
24// may be used with Equal and Diff.
25type Option interface {
26 // filter applies all filters and returns the option that remains.
27 // Each option may only read s.curPath and call s.callTTBFunc.
28 //
29 // An Options is returned only if multiple comparers or transformers
30 // can apply simultaneously and will only contain values of those types
31 // or sub-Options containing values of those types.
32 filter(s *state, vx, vy reflect.Value, t reflect.Type) applicableOption
33}
34
35// applicableOption represents the following types:
36// Fundamental: ignore | invalid | *comparer | *transformer
37// Grouping: Options
38type applicableOption interface {
39 Option
40
41 // apply executes the option, which may mutate s or panic.
42 apply(s *state, vx, vy reflect.Value)
43}
44
45// coreOption represents the following types:
46// Fundamental: ignore | invalid | *comparer | *transformer
47// Filters: *pathFilter | *valuesFilter
48type coreOption interface {
49 Option
50 isCore()
51}
52
53type core struct{}
54
55func (core) isCore() {}
56
57// Options is a list of Option values that also satisfies the Option interface.
58// Helper comparison packages may return an Options value when packing multiple
59// Option values into a single Option. When this package processes an Options,
60// it will be implicitly expanded into a flat list.
61//
62// Applying a filter on an Options is equivalent to applying that same filter
63// on all individual options held within.
64type Options []Option
65
66func (opts Options) filter(s *state, vx, vy reflect.Value, t reflect.Type) (out applicableOption) {
67 for _, opt := range opts {
68 switch opt := opt.filter(s, vx, vy, t); opt.(type) {
69 case ignore:
70 return ignore{} // Only ignore can short-circuit evaluation
71 case invalid:
72 out = invalid{} // Takes precedence over comparer or transformer
73 case *comparer, *transformer, Options:
74 switch out.(type) {
75 case nil:
76 out = opt
77 case invalid:
78 // Keep invalid
79 case *comparer, *transformer, Options:
80 out = Options{out, opt} // Conflicting comparers or transformers
81 }
82 }
83 }
84 return out
85}
86
87func (opts Options) apply(s *state, _, _ reflect.Value) {
88 const warning = "ambiguous set of applicable options"
89 const help = "consider using filters to ensure at most one Comparer or Transformer may apply"
90 var ss []string
91 for _, opt := range flattenOptions(nil, opts) {
92 ss = append(ss, fmt.Sprint(opt))
93 }
94 set := strings.Join(ss, "\n\t")
95 panic(fmt.Sprintf("%s at %#v:\n\t%s\n%s", warning, s.curPath, set, help))
96}
97
98func (opts Options) String() string {
99 var ss []string
100 for _, opt := range opts {
101 ss = append(ss, fmt.Sprint(opt))
102 }
103 return fmt.Sprintf("Options{%s}", strings.Join(ss, ", "))
104}
105
106// FilterPath returns a new Option where opt is only evaluated if filter f
107// returns true for the current Path in the value tree.
108//
109// The option passed in may be an Ignore, Transformer, Comparer, Options, or
110// a previously filtered Option.
111func FilterPath(f func(Path) bool, opt Option) Option {
112 if f == nil {
113 panic("invalid path filter function")
114 }
115 if opt := normalizeOption(opt); opt != nil {
116 return &pathFilter{fnc: f, opt: opt}
117 }
118 return nil
119}
120
121type pathFilter struct {
122 core
123 fnc func(Path) bool
124 opt Option
125}
126
127func (f pathFilter) filter(s *state, vx, vy reflect.Value, t reflect.Type) applicableOption {
128 if f.fnc(s.curPath) {
129 return f.opt.filter(s, vx, vy, t)
130 }
131 return nil
132}
133
134func (f pathFilter) String() string {
135 fn := getFuncName(reflect.ValueOf(f.fnc).Pointer())
136 return fmt.Sprintf("FilterPath(%s, %v)", fn, f.opt)
137}
138
139// FilterValues returns a new Option where opt is only evaluated if filter f,
140// which is a function of the form "func(T, T) bool", returns true for the
141// current pair of values being compared. If the type of the values is not
142// assignable to T, then this filter implicitly returns false.
143//
144// The filter function must be
145// symmetric (i.e., agnostic to the order of the inputs) and
146// deterministic (i.e., produces the same result when given the same inputs).
147// If T is an interface, it is possible that f is called with two values with
148// different concrete types that both implement T.
149//
150// The option passed in may be an Ignore, Transformer, Comparer, Options, or
151// a previously filtered Option.
152func FilterValues(f interface{}, opt Option) Option {
153 v := reflect.ValueOf(f)
154 if !function.IsType(v.Type(), function.ValueFilter) || v.IsNil() {
155 panic(fmt.Sprintf("invalid values filter function: %T", f))
156 }
157 if opt := normalizeOption(opt); opt != nil {
158 vf := &valuesFilter{fnc: v, opt: opt}
159 if ti := v.Type().In(0); ti.Kind() != reflect.Interface || ti.NumMethod() > 0 {
160 vf.typ = ti
161 }
162 return vf
163 }
164 return nil
165}
166
167type valuesFilter struct {
168 core
169 typ reflect.Type // T
170 fnc reflect.Value // func(T, T) bool
171 opt Option
172}
173
174func (f valuesFilter) filter(s *state, vx, vy reflect.Value, t reflect.Type) applicableOption {
175 if !vx.IsValid() || !vy.IsValid() {
176 return invalid{}
177 }
178 if (f.typ == nil || t.AssignableTo(f.typ)) && s.callTTBFunc(f.fnc, vx, vy) {
179 return f.opt.filter(s, vx, vy, t)
180 }
181 return nil
182}
183
184func (f valuesFilter) String() string {
185 fn := getFuncName(f.fnc.Pointer())
186 return fmt.Sprintf("FilterValues(%s, %v)", fn, f.opt)
187}
188
189// Ignore is an Option that causes all comparisons to be ignored.
190// This value is intended to be combined with FilterPath or FilterValues.
191// It is an error to pass an unfiltered Ignore option to Equal.
192func Ignore() Option { return ignore{} }
193
194type ignore struct{ core }
195
196func (ignore) isFiltered() bool { return false }
197func (ignore) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return ignore{} }
198func (ignore) apply(_ *state, _, _ reflect.Value) { return }
199func (ignore) String() string { return "Ignore()" }
200
201// invalid is a sentinel Option type to indicate that some options could not
202// be evaluated due to unexported fields.
203type invalid struct{ core }
204
205func (invalid) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return invalid{} }
206func (invalid) apply(s *state, _, _ reflect.Value) {
207 const help = "consider using AllowUnexported or cmpopts.IgnoreUnexported"
208 panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help))
209}
210
211// Transformer returns an Option that applies a transformation function that
212// converts values of a certain type into that of another.
213//
214// The transformer f must be a function "func(T) R" that converts values of
215// type T to those of type R and is implicitly filtered to input values
216// assignable to T. The transformer must not mutate T in any way.
217//
218// To help prevent some cases of infinite recursive cycles applying the
219// same transform to the output of itself (e.g., in the case where the
220// input and output types are the same), an implicit filter is added such that
221// a transformer is applicable only if that exact transformer is not already
222// in the tail of the Path since the last non-Transform step.
223//
224// The name is a user provided label that is used as the Transform.Name in the
225// transformation PathStep. If empty, an arbitrary name is used.
226func Transformer(name string, f interface{}) Option {
227 v := reflect.ValueOf(f)
228 if !function.IsType(v.Type(), function.Transformer) || v.IsNil() {
229 panic(fmt.Sprintf("invalid transformer function: %T", f))
230 }
231 if name == "" {
232 name = "λ" // Lambda-symbol as place-holder for anonymous transformer
233 }
234 if !isValid(name) {
235 panic(fmt.Sprintf("invalid name: %q", name))
236 }
237 tr := &transformer{name: name, fnc: reflect.ValueOf(f)}
238 if ti := v.Type().In(0); ti.Kind() != reflect.Interface || ti.NumMethod() > 0 {
239 tr.typ = ti
240 }
241 return tr
242}
243
244type transformer struct {
245 core
246 name string
247 typ reflect.Type // T
248 fnc reflect.Value // func(T) R
249}
250
251func (tr *transformer) isFiltered() bool { return tr.typ != nil }
252
253func (tr *transformer) filter(s *state, _, _ reflect.Value, t reflect.Type) applicableOption {
254 for i := len(s.curPath) - 1; i >= 0; i-- {
255 if t, ok := s.curPath[i].(*transform); !ok {
256 break // Hit most recent non-Transform step
257 } else if tr == t.trans {
258 return nil // Cannot directly use same Transform
259 }
260 }
261 if tr.typ == nil || t.AssignableTo(tr.typ) {
262 return tr
263 }
264 return nil
265}
266
267func (tr *transformer) apply(s *state, vx, vy reflect.Value) {
268 // Update path before calling the Transformer so that dynamic checks
269 // will use the updated path.
270 s.curPath.push(&transform{pathStep{tr.fnc.Type().Out(0)}, tr})
271 defer s.curPath.pop()
272
273 vx = s.callTRFunc(tr.fnc, vx)
274 vy = s.callTRFunc(tr.fnc, vy)
275 s.compareAny(vx, vy)
276}
277
278func (tr transformer) String() string {
279 return fmt.Sprintf("Transformer(%s, %s)", tr.name, getFuncName(tr.fnc.Pointer()))
280}
281
282// Comparer returns an Option that determines whether two values are equal
283// to each other.
284//
285// The comparer f must be a function "func(T, T) bool" and is implicitly
286// filtered to input values assignable to T. If T is an interface, it is
287// possible that f is called with two values of different concrete types that
288// both implement T.
289//
290// The equality function must be:
291// • Symmetric: equal(x, y) == equal(y, x)
292// • Deterministic: equal(x, y) == equal(x, y)
293// • Pure: equal(x, y) does not modify x or y
294func Comparer(f interface{}) Option {
295 v := reflect.ValueOf(f)
296 if !function.IsType(v.Type(), function.Equal) || v.IsNil() {
297 panic(fmt.Sprintf("invalid comparer function: %T", f))
298 }
299 cm := &comparer{fnc: v}
300 if ti := v.Type().In(0); ti.Kind() != reflect.Interface || ti.NumMethod() > 0 {
301 cm.typ = ti
302 }
303 return cm
304}
305
306type comparer struct {
307 core
308 typ reflect.Type // T
309 fnc reflect.Value // func(T, T) bool
310}
311
312func (cm *comparer) isFiltered() bool { return cm.typ != nil }
313
314func (cm *comparer) filter(_ *state, _, _ reflect.Value, t reflect.Type) applicableOption {
315 if cm.typ == nil || t.AssignableTo(cm.typ) {
316 return cm
317 }
318 return nil
319}
320
321func (cm *comparer) apply(s *state, vx, vy reflect.Value) {
322 eq := s.callTTBFunc(cm.fnc, vx, vy)
323 s.report(eq, vx, vy)
324}
325
326func (cm comparer) String() string {
327 return fmt.Sprintf("Comparer(%s)", getFuncName(cm.fnc.Pointer()))
328}
329
330// AllowUnexported returns an Option that forcibly allows operations on
331// unexported fields in certain structs, which are specified by passing in a
332// value of each struct type.
333//
334// Users of this option must understand that comparing on unexported fields
335// from external packages is not safe since changes in the internal
336// implementation of some external package may cause the result of Equal
337// to unexpectedly change. However, it may be valid to use this option on types
338// defined in an internal package where the semantic meaning of an unexported
339// field is in the control of the user.
340//
341// For some cases, a custom Comparer should be used instead that defines
342// equality as a function of the public API of a type rather than the underlying
343// unexported implementation.
344//
345// For example, the reflect.Type documentation defines equality to be determined
346// by the == operator on the interface (essentially performing a shallow pointer
347// comparison) and most attempts to compare *regexp.Regexp types are interested
348// in only checking that the regular expression strings are equal.
349// Both of these are accomplished using Comparers:
350//
351// Comparer(func(x, y reflect.Type) bool { return x == y })
352// Comparer(func(x, y *regexp.Regexp) bool { return x.String() == y.String() })
353//
354// In other cases, the cmpopts.IgnoreUnexported option can be used to ignore
355// all unexported fields on specified struct types.
356func AllowUnexported(types ...interface{}) Option {
357 if !supportAllowUnexported {
358 panic("AllowUnexported is not supported on purego builds, Google App Engine Standard, or GopherJS")
359 }
360 m := make(map[reflect.Type]bool)
361 for _, typ := range types {
362 t := reflect.TypeOf(typ)
363 if t.Kind() != reflect.Struct {
364 panic(fmt.Sprintf("invalid struct type: %T", typ))
365 }
366 m[t] = true
367 }
368 return visibleStructs(m)
369}
370
371type visibleStructs map[reflect.Type]bool
372
373func (visibleStructs) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption {
374 panic("not implemented")
375}
376
377// reporter is an Option that configures how differences are reported.
378type reporter interface {
379 // TODO: Not exported yet.
380 //
381 // Perhaps add PushStep and PopStep and change Report to only accept
382 // a PathStep instead of the full-path? Adding a PushStep and PopStep makes
383 // it clear that we are traversing the value tree in a depth-first-search
384 // manner, which has an effect on how values are printed.
385
386 Option
387
388 // Report is called for every comparison made and will be provided with
389 // the two values being compared, the equality result, and the
390 // current path in the value tree. It is possible for x or y to be an
391 // invalid reflect.Value if one of the values is non-existent;
392 // which is possible with maps and slices.
393 Report(x, y reflect.Value, eq bool, p Path)
394}
395
396// normalizeOption normalizes the input options such that all Options groups
397// are flattened and groups with a single element are reduced to that element.
398// Only coreOptions and Options containing coreOptions are allowed.
399func normalizeOption(src Option) Option {
400 switch opts := flattenOptions(nil, Options{src}); len(opts) {
401 case 0:
402 return nil
403 case 1:
404 return opts[0]
405 default:
406 return opts
407 }
408}
409
410// flattenOptions copies all options in src to dst as a flat list.
411// Only coreOptions and Options containing coreOptions are allowed.
412func flattenOptions(dst, src Options) Options {
413 for _, opt := range src {
414 switch opt := opt.(type) {
415 case nil:
416 continue
417 case Options:
418 dst = flattenOptions(dst, opt)
419 case coreOption:
420 dst = append(dst, opt)
421 default:
422 panic(fmt.Sprintf("invalid option type: %T", opt))
423 }
424 }
425 return dst
426}
427
428// getFuncName returns a short function name from the pointer.
429// The string parsing logic works up until Go1.9.
430func getFuncName(p uintptr) string {
431 fnc := runtime.FuncForPC(p)
432 if fnc == nil {
433 return "<unknown>"
434 }
435 name := fnc.Name() // E.g., "long/path/name/mypkg.(mytype).(long/path/name/mypkg.myfunc)-fm"
436 if strings.HasSuffix(name, ")-fm") || strings.HasSuffix(name, ")·fm") {
437 // Strip the package name from method name.
438 name = strings.TrimSuffix(name, ")-fm")
439 name = strings.TrimSuffix(name, ")·fm")
440 if i := strings.LastIndexByte(name, '('); i >= 0 {
441 methodName := name[i+1:] // E.g., "long/path/name/mypkg.myfunc"
442 if j := strings.LastIndexByte(methodName, '.'); j >= 0 {
443 methodName = methodName[j+1:] // E.g., "myfunc"
444 }
445 name = name[:i] + methodName // E.g., "long/path/name/mypkg.(mytype)." + "myfunc"
446 }
447 }
448 if i := strings.LastIndexByte(name, '/'); i >= 0 {
449 // Strip the package name.
450 name = name[i+1:] // E.g., "mypkg.(mytype).myfunc"
451 }
452 return name
453}
diff --git a/vendor/github.com/google/go-cmp/cmp/path.go b/vendor/github.com/google/go-cmp/cmp/path.go
new file mode 100644
index 0000000..c08a3cf
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/path.go
@@ -0,0 +1,309 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5package cmp
6
7import (
8 "fmt"
9 "reflect"
10 "strings"
11 "unicode"
12 "unicode/utf8"
13)
14
15type (
16 // Path is a list of PathSteps describing the sequence of operations to get
17 // from some root type to the current position in the value tree.
18 // The first Path element is always an operation-less PathStep that exists
19 // simply to identify the initial type.
20 //
21 // When traversing structs with embedded structs, the embedded struct will
22 // always be accessed as a field before traversing the fields of the
23 // embedded struct themselves. That is, an exported field from the
24 // embedded struct will never be accessed directly from the parent struct.
25 Path []PathStep
26
27 // PathStep is a union-type for specific operations to traverse
28 // a value's tree structure. Users of this package never need to implement
29 // these types as values of this type will be returned by this package.
30 PathStep interface {
31 String() string
32 Type() reflect.Type // Resulting type after performing the path step
33 isPathStep()
34 }
35
36 // SliceIndex is an index operation on a slice or array at some index Key.
37 SliceIndex interface {
38 PathStep
39 Key() int // May return -1 if in a split state
40
41 // SplitKeys returns the indexes for indexing into slices in the
42 // x and y values, respectively. These indexes may differ due to the
43 // insertion or removal of an element in one of the slices, causing
44 // all of the indexes to be shifted. If an index is -1, then that
45 // indicates that the element does not exist in the associated slice.
46 //
47 // Key is guaranteed to return -1 if and only if the indexes returned
48 // by SplitKeys are not the same. SplitKeys will never return -1 for
49 // both indexes.
50 SplitKeys() (x int, y int)
51
52 isSliceIndex()
53 }
54 // MapIndex is an index operation on a map at some index Key.
55 MapIndex interface {
56 PathStep
57 Key() reflect.Value
58 isMapIndex()
59 }
60 // TypeAssertion represents a type assertion on an interface.
61 TypeAssertion interface {
62 PathStep
63 isTypeAssertion()
64 }
65 // StructField represents a struct field access on a field called Name.
66 StructField interface {
67 PathStep
68 Name() string
69 Index() int
70 isStructField()
71 }
72 // Indirect represents pointer indirection on the parent type.
73 Indirect interface {
74 PathStep
75 isIndirect()
76 }
77 // Transform is a transformation from the parent type to the current type.
78 Transform interface {
79 PathStep
80 Name() string
81 Func() reflect.Value
82
83 // Option returns the originally constructed Transformer option.
84 // The == operator can be used to detect the exact option used.
85 Option() Option
86
87 isTransform()
88 }
89)
90
91func (pa *Path) push(s PathStep) {
92 *pa = append(*pa, s)
93}
94
95func (pa *Path) pop() {
96 *pa = (*pa)[:len(*pa)-1]
97}
98
99// Last returns the last PathStep in the Path.
100// If the path is empty, this returns a non-nil PathStep that reports a nil Type.
101func (pa Path) Last() PathStep {
102 return pa.Index(-1)
103}
104
105// Index returns the ith step in the Path and supports negative indexing.
106// A negative index starts counting from the tail of the Path such that -1
107// refers to the last step, -2 refers to the second-to-last step, and so on.
108// If index is invalid, this returns a non-nil PathStep that reports a nil Type.
109func (pa Path) Index(i int) PathStep {
110 if i < 0 {
111 i = len(pa) + i
112 }
113 if i < 0 || i >= len(pa) {
114 return pathStep{}
115 }
116 return pa[i]
117}
118
119// String returns the simplified path to a node.
120// The simplified path only contains struct field accesses.
121//
122// For example:
123// MyMap.MySlices.MyField
124func (pa Path) String() string {
125 var ss []string
126 for _, s := range pa {
127 if _, ok := s.(*structField); ok {
128 ss = append(ss, s.String())
129 }
130 }
131 return strings.TrimPrefix(strings.Join(ss, ""), ".")
132}
133
134// GoString returns the path to a specific node using Go syntax.
135//
136// For example:
137// (*root.MyMap["key"].(*mypkg.MyStruct).MySlices)[2][3].MyField
138func (pa Path) GoString() string {
139 var ssPre, ssPost []string
140 var numIndirect int
141 for i, s := range pa {
142 var nextStep PathStep
143 if i+1 < len(pa) {
144 nextStep = pa[i+1]
145 }
146 switch s := s.(type) {
147 case *indirect:
148 numIndirect++
149 pPre, pPost := "(", ")"
150 switch nextStep.(type) {
151 case *indirect:
152 continue // Next step is indirection, so let them batch up
153 case *structField:
154 numIndirect-- // Automatic indirection on struct fields
155 case nil:
156 pPre, pPost = "", "" // Last step; no need for parenthesis
157 }
158 if numIndirect > 0 {
159 ssPre = append(ssPre, pPre+strings.Repeat("*", numIndirect))
160 ssPost = append(ssPost, pPost)
161 }
162 numIndirect = 0
163 continue
164 case *transform:
165 ssPre = append(ssPre, s.trans.name+"(")
166 ssPost = append(ssPost, ")")
167 continue
168 case *typeAssertion:
169 // As a special-case, elide type assertions on anonymous types
170 // since they are typically generated dynamically and can be very
171 // verbose. For example, some transforms return interface{} because
172 // of Go's lack of generics, but typically take in and return the
173 // exact same concrete type.
174 if s.Type().PkgPath() == "" {
175 continue
176 }
177 }
178 ssPost = append(ssPost, s.String())
179 }
180 for i, j := 0, len(ssPre)-1; i < j; i, j = i+1, j-1 {
181 ssPre[i], ssPre[j] = ssPre[j], ssPre[i]
182 }
183 return strings.Join(ssPre, "") + strings.Join(ssPost, "")
184}
185
186type (
187 pathStep struct {
188 typ reflect.Type
189 }
190
191 sliceIndex struct {
192 pathStep
193 xkey, ykey int
194 }
195 mapIndex struct {
196 pathStep
197 key reflect.Value
198 }
199 typeAssertion struct {
200 pathStep
201 }
202 structField struct {
203 pathStep
204 name string
205 idx int
206
207 // These fields are used for forcibly accessing an unexported field.
208 // pvx, pvy, and field are only valid if unexported is true.
209 unexported bool
210 force bool // Forcibly allow visibility
211 pvx, pvy reflect.Value // Parent values
212 field reflect.StructField // Field information
213 }
214 indirect struct {
215 pathStep
216 }
217 transform struct {
218 pathStep
219 trans *transformer
220 }
221)
222
223func (ps pathStep) Type() reflect.Type { return ps.typ }
224func (ps pathStep) String() string {
225 if ps.typ == nil {
226 return "<nil>"
227 }
228 s := ps.typ.String()
229 if s == "" || strings.ContainsAny(s, "{}\n") {
230 return "root" // Type too simple or complex to print
231 }
232 return fmt.Sprintf("{%s}", s)
233}
234
235func (si sliceIndex) String() string {
236 switch {
237 case si.xkey == si.ykey:
238 return fmt.Sprintf("[%d]", si.xkey)
239 case si.ykey == -1:
240 // [5->?] means "I don't know where X[5] went"
241 return fmt.Sprintf("[%d->?]", si.xkey)
242 case si.xkey == -1:
243 // [?->3] means "I don't know where Y[3] came from"
244 return fmt.Sprintf("[?->%d]", si.ykey)
245 default:
246 // [5->3] means "X[5] moved to Y[3]"
247 return fmt.Sprintf("[%d->%d]", si.xkey, si.ykey)
248 }
249}
250func (mi mapIndex) String() string { return fmt.Sprintf("[%#v]", mi.key) }
251func (ta typeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) }
252func (sf structField) String() string { return fmt.Sprintf(".%s", sf.name) }
253func (in indirect) String() string { return "*" }
254func (tf transform) String() string { return fmt.Sprintf("%s()", tf.trans.name) }
255
256func (si sliceIndex) Key() int {
257 if si.xkey != si.ykey {
258 return -1
259 }
260 return si.xkey
261}
262func (si sliceIndex) SplitKeys() (x, y int) { return si.xkey, si.ykey }
263func (mi mapIndex) Key() reflect.Value { return mi.key }
264func (sf structField) Name() string { return sf.name }
265func (sf structField) Index() int { return sf.idx }
266func (tf transform) Name() string { return tf.trans.name }
267func (tf transform) Func() reflect.Value { return tf.trans.fnc }
268func (tf transform) Option() Option { return tf.trans }
269
270func (pathStep) isPathStep() {}
271func (sliceIndex) isSliceIndex() {}
272func (mapIndex) isMapIndex() {}
273func (typeAssertion) isTypeAssertion() {}
274func (structField) isStructField() {}
275func (indirect) isIndirect() {}
276func (transform) isTransform() {}
277
278var (
279 _ SliceIndex = sliceIndex{}
280 _ MapIndex = mapIndex{}
281 _ TypeAssertion = typeAssertion{}
282 _ StructField = structField{}
283 _ Indirect = indirect{}
284 _ Transform = transform{}
285
286 _ PathStep = sliceIndex{}
287 _ PathStep = mapIndex{}
288 _ PathStep = typeAssertion{}
289 _ PathStep = structField{}
290 _ PathStep = indirect{}
291 _ PathStep = transform{}
292)
293
294// isExported reports whether the identifier is exported.
295func isExported(id string) bool {
296 r, _ := utf8.DecodeRuneInString(id)
297 return unicode.IsUpper(r)
298}
299
300// isValid reports whether the identifier is valid.
301// Empty and underscore-only strings are not valid.
302func isValid(id string) bool {
303 ok := id != "" && id != "_"
304 for j, c := range id {
305 ok = ok && (j > 0 || !unicode.IsDigit(c))
306 ok = ok && (c == '_' || unicode.IsLetter(c) || unicode.IsDigit(c))
307 }
308 return ok
309}
diff --git a/vendor/github.com/google/go-cmp/cmp/reporter.go b/vendor/github.com/google/go-cmp/cmp/reporter.go
new file mode 100644
index 0000000..20e9f18
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/reporter.go
@@ -0,0 +1,53 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5package cmp
6
7import (
8 "fmt"
9 "reflect"
10 "strings"
11
12 "github.com/google/go-cmp/cmp/internal/value"
13)
14
15type defaultReporter struct {
16 Option
17 diffs []string // List of differences, possibly truncated
18 ndiffs int // Total number of differences
19 nbytes int // Number of bytes in diffs
20 nlines int // Number of lines in diffs
21}
22
23var _ reporter = (*defaultReporter)(nil)
24
25func (r *defaultReporter) Report(x, y reflect.Value, eq bool, p Path) {
26 if eq {
27 return // Ignore equal results
28 }
29 const maxBytes = 4096
30 const maxLines = 256
31 r.ndiffs++
32 if r.nbytes < maxBytes && r.nlines < maxLines {
33 sx := value.Format(x, value.FormatConfig{UseStringer: true})
34 sy := value.Format(y, value.FormatConfig{UseStringer: true})
35 if sx == sy {
36 // Unhelpful output, so use more exact formatting.
37 sx = value.Format(x, value.FormatConfig{PrintPrimitiveType: true})
38 sy = value.Format(y, value.FormatConfig{PrintPrimitiveType: true})
39 }
40 s := fmt.Sprintf("%#v:\n\t-: %s\n\t+: %s\n", p, sx, sy)
41 r.diffs = append(r.diffs, s)
42 r.nbytes += len(s)
43 r.nlines += strings.Count(s, "\n")
44 }
45}
46
47func (r *defaultReporter) String() string {
48 s := strings.Join(r.diffs, "")
49 if r.ndiffs == len(r.diffs) {
50 return s
51 }
52 return fmt.Sprintf("%s... %d more differences ...", s, r.ndiffs-len(r.diffs))
53}
diff --git a/vendor/github.com/google/go-cmp/cmp/unsafe_panic.go b/vendor/github.com/google/go-cmp/cmp/unsafe_panic.go
new file mode 100644
index 0000000..d1518eb
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/unsafe_panic.go
@@ -0,0 +1,15 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// +build purego appengine js
6
7package cmp
8
9import "reflect"
10
11const supportAllowUnexported = false
12
13func unsafeRetrieveField(reflect.Value, reflect.StructField) reflect.Value {
14 panic("unsafeRetrieveField is not implemented")
15}
diff --git a/vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go b/vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go
new file mode 100644
index 0000000..579b655
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go
@@ -0,0 +1,23 @@
1// Copyright 2017, The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// +build !purego,!appengine,!js
6
7package cmp
8
9import (
10 "reflect"
11 "unsafe"
12)
13
14const supportAllowUnexported = true
15
16// unsafeRetrieveField uses unsafe to forcibly retrieve any field from a struct
17// such that the value has read-write permissions.
18//
19// The parent struct, v, must be addressable, while f must be a StructField
20// describing the field to retrieve.
21func unsafeRetrieveField(v reflect.Value, f reflect.StructField) reflect.Value {
22 return reflect.NewAt(f.Type, unsafe.Pointer(v.UnsafeAddr()+f.Offset)).Elem()
23}