diff options
Diffstat (limited to 'vendor/github.com/google')
-rw-r--r-- | vendor/github.com/google/go-cmp/LICENSE | 27 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/compare.go | 553 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go | 17 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go | 122 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go | 363 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/function/func.go | 49 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/value/format.go | 277 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/value/sort.go | 111 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/options.go | 453 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/path.go | 309 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/reporter.go | 53 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/unsafe_panic.go | 15 | ||||
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go | 23 |
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 @@ | |||
1 | Copyright (c) 2017 The Go Authors. All rights reserved. | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are | ||
5 | met: | ||
6 | |||
7 | * Redistributions of source code must retain the above copyright | ||
8 | notice, this list of conditions and the following disclaimer. | ||
9 | * Redistributions in binary form must reproduce the above | ||
10 | copyright notice, this list of conditions and the following disclaimer | ||
11 | in the documentation and/or other materials provided with the | ||
12 | distribution. | ||
13 | * Neither the name of Google Inc. nor the names of its | ||
14 | contributors may be used to endorse or promote products derived from | ||
15 | this software without specific prior written permission. | ||
16 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
27 | OF 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. | ||
27 | package cmp | ||
28 | |||
29 | import ( | ||
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 | |||
44 | var 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. | ||
84 | func 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. | ||
97 | func 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 | |||
108 | type 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 | |||
124 | func newState(opts []Option) *state { | ||
125 | s := new(state) | ||
126 | for _, opt := range opts { | ||
127 | s.processOption(opt) | ||
128 | } | ||
129 | return s | ||
130 | } | ||
131 | |||
132 | func (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. | ||
167 | func (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 | |||
182 | func (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 | |||
279 | func (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 | |||
296 | func (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 | |||
313 | func (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 | |||
325 | func (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 | |||
349 | func (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 | |||
370 | func 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. | ||
382 | func 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 | |||
391 | func (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 | |||
443 | func (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 | |||
475 | func (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. | ||
509 | func (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. | ||
523 | type 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. | ||
533 | func (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. | ||
546 | func 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 | |||
7 | package diff | ||
8 | |||
9 | var debug debugger | ||
10 | |||
11 | type debugger struct{} | ||
12 | |||
13 | func (debugger) Begin(_, _ int, f EqualFunc, _, _ *EditScript) EqualFunc { | ||
14 | return f | ||
15 | } | ||
16 | func (debugger) Update() {} | ||
17 | func (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 | |||
7 | package diff | ||
8 | |||
9 | import ( | ||
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 | |||
55 | const ( | ||
56 | updateDelay = 100 * time.Millisecond | ||
57 | finishDelay = 500 * time.Millisecond | ||
58 | ansiTerminal = true // ANSI escape codes used to move terminal cursor | ||
59 | ) | ||
60 | |||
61 | var debug debugger | ||
62 | |||
63 | type debugger struct { | ||
64 | sync.Mutex | ||
65 | p1, p2 EditScript | ||
66 | fwdPath, revPath *EditScript | ||
67 | grid []byte | ||
68 | lines int | ||
69 | } | ||
70 | |||
71 | func (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 | |||
99 | func (dbg *debugger) Update() { | ||
100 | dbg.print(updateDelay) | ||
101 | } | ||
102 | |||
103 | func (dbg *debugger) Finish() { | ||
104 | dbg.print(finishDelay) | ||
105 | dbg.Unlock() | ||
106 | } | ||
107 | |||
108 | func (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 | |||
116 | func (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. | ||
13 | package diff | ||
14 | |||
15 | // EditType represents a single operation within an edit-script. | ||
16 | type EditType uint8 | ||
17 | |||
18 | const ( | ||
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. | ||
30 | type 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. | ||
35 | func (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. | ||
55 | func (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. | ||
75 | func (es EditScript) Dist() int { return len(es) - es.stats().NI } | ||
76 | |||
77 | // LenX is the length of the X list. | ||
78 | func (es EditScript) LenX() int { return len(es) - es.stats().NY } | ||
79 | |||
80 | // LenY is the length of the Y list. | ||
81 | func (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. | ||
85 | type 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. | ||
90 | type 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. | ||
94 | func (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. | ||
101 | func (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. | ||
120 | func 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 | |||
287 | type 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. | ||
295 | func (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 | |||
339 | func (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 | |||
352 | type point struct{ X, Y int } | ||
353 | |||
354 | func (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 ...] | ||
358 | func 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. | ||
6 | package function | ||
7 | |||
8 | import "reflect" | ||
9 | |||
10 | type funcType int | ||
11 | |||
12 | const ( | ||
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 | |||
26 | var boolType = reflect.TypeOf(true) | ||
27 | |||
28 | // IsType reports whether the reflect.Type is of the specified function type. | ||
29 | func 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. | ||
6 | package value | ||
7 | |||
8 | import ( | ||
9 | "fmt" | ||
10 | "reflect" | ||
11 | "strconv" | ||
12 | "strings" | ||
13 | "unicode" | ||
14 | ) | ||
15 | |||
16 | var 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 | ||
25 | func 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 | |||
32 | type 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 | |||
40 | func 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 | |||
171 | func 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 | |||
190 | func 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 | |||
197 | func 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 | |||
209 | func 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. | ||
233 | func 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. | ||
243 | func 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 | |||
5 | package value | ||
6 | |||
7 | import ( | ||
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. | ||
16 | func 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. | ||
35 | type valueSorter []reflect.Value | ||
36 | |||
37 | func (vs valueSorter) Len() int { return len(vs) } | ||
38 | func (vs valueSorter) Less(i, j int) bool { return isLess(vs[i], vs[j]) } | ||
39 | func (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. | ||
43 | func 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 | |||
5 | package cmp | ||
6 | |||
7 | import ( | ||
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. | ||
25 | type 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 | ||
38 | type 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 | ||
48 | type coreOption interface { | ||
49 | Option | ||
50 | isCore() | ||
51 | } | ||
52 | |||
53 | type core struct{} | ||
54 | |||
55 | func (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. | ||
64 | type Options []Option | ||
65 | |||
66 | func (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 | |||
87 | func (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 | |||
98 | func (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. | ||
111 | func 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 | |||
121 | type pathFilter struct { | ||
122 | core | ||
123 | fnc func(Path) bool | ||
124 | opt Option | ||
125 | } | ||
126 | |||
127 | func (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 | |||
134 | func (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. | ||
152 | func 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 | |||
167 | type valuesFilter struct { | ||
168 | core | ||
169 | typ reflect.Type // T | ||
170 | fnc reflect.Value // func(T, T) bool | ||
171 | opt Option | ||
172 | } | ||
173 | |||
174 | func (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 | |||
184 | func (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. | ||
192 | func Ignore() Option { return ignore{} } | ||
193 | |||
194 | type ignore struct{ core } | ||
195 | |||
196 | func (ignore) isFiltered() bool { return false } | ||
197 | func (ignore) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return ignore{} } | ||
198 | func (ignore) apply(_ *state, _, _ reflect.Value) { return } | ||
199 | func (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. | ||
203 | type invalid struct{ core } | ||
204 | |||
205 | func (invalid) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return invalid{} } | ||
206 | func (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. | ||
226 | func 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 | |||
244 | type transformer struct { | ||
245 | core | ||
246 | name string | ||
247 | typ reflect.Type // T | ||
248 | fnc reflect.Value // func(T) R | ||
249 | } | ||
250 | |||
251 | func (tr *transformer) isFiltered() bool { return tr.typ != nil } | ||
252 | |||
253 | func (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 | |||
267 | func (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 | |||
278 | func (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 | ||
294 | func 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 | |||
306 | type comparer struct { | ||
307 | core | ||
308 | typ reflect.Type // T | ||
309 | fnc reflect.Value // func(T, T) bool | ||
310 | } | ||
311 | |||
312 | func (cm *comparer) isFiltered() bool { return cm.typ != nil } | ||
313 | |||
314 | func (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 | |||
321 | func (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 | |||
326 | func (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. | ||
356 | func 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 | |||
371 | type visibleStructs map[reflect.Type]bool | ||
372 | |||
373 | func (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. | ||
378 | type 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. | ||
399 | func 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. | ||
412 | func 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. | ||
430 | func 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 | |||
5 | package cmp | ||
6 | |||
7 | import ( | ||
8 | "fmt" | ||
9 | "reflect" | ||
10 | "strings" | ||
11 | "unicode" | ||
12 | "unicode/utf8" | ||
13 | ) | ||
14 | |||
15 | type ( | ||
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 | |||
91 | func (pa *Path) push(s PathStep) { | ||
92 | *pa = append(*pa, s) | ||
93 | } | ||
94 | |||
95 | func (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. | ||
101 | func (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. | ||
109 | func (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 | ||
124 | func (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 | ||
138 | func (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 | |||
186 | type ( | ||
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 | |||
223 | func (ps pathStep) Type() reflect.Type { return ps.typ } | ||
224 | func (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 | |||
235 | func (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 | } | ||
250 | func (mi mapIndex) String() string { return fmt.Sprintf("[%#v]", mi.key) } | ||
251 | func (ta typeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) } | ||
252 | func (sf structField) String() string { return fmt.Sprintf(".%s", sf.name) } | ||
253 | func (in indirect) String() string { return "*" } | ||
254 | func (tf transform) String() string { return fmt.Sprintf("%s()", tf.trans.name) } | ||
255 | |||
256 | func (si sliceIndex) Key() int { | ||
257 | if si.xkey != si.ykey { | ||
258 | return -1 | ||
259 | } | ||
260 | return si.xkey | ||
261 | } | ||
262 | func (si sliceIndex) SplitKeys() (x, y int) { return si.xkey, si.ykey } | ||
263 | func (mi mapIndex) Key() reflect.Value { return mi.key } | ||
264 | func (sf structField) Name() string { return sf.name } | ||
265 | func (sf structField) Index() int { return sf.idx } | ||
266 | func (tf transform) Name() string { return tf.trans.name } | ||
267 | func (tf transform) Func() reflect.Value { return tf.trans.fnc } | ||
268 | func (tf transform) Option() Option { return tf.trans } | ||
269 | |||
270 | func (pathStep) isPathStep() {} | ||
271 | func (sliceIndex) isSliceIndex() {} | ||
272 | func (mapIndex) isMapIndex() {} | ||
273 | func (typeAssertion) isTypeAssertion() {} | ||
274 | func (structField) isStructField() {} | ||
275 | func (indirect) isIndirect() {} | ||
276 | func (transform) isTransform() {} | ||
277 | |||
278 | var ( | ||
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. | ||
295 | func 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. | ||
302 | func 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 | |||
5 | package cmp | ||
6 | |||
7 | import ( | ||
8 | "fmt" | ||
9 | "reflect" | ||
10 | "strings" | ||
11 | |||
12 | "github.com/google/go-cmp/cmp/internal/value" | ||
13 | ) | ||
14 | |||
15 | type 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 | |||
23 | var _ reporter = (*defaultReporter)(nil) | ||
24 | |||
25 | func (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 | |||
47 | func (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 | |||
7 | package cmp | ||
8 | |||
9 | import "reflect" | ||
10 | |||
11 | const supportAllowUnexported = false | ||
12 | |||
13 | func 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 | |||
7 | package cmp | ||
8 | |||
9 | import ( | ||
10 | "reflect" | ||
11 | "unsafe" | ||
12 | ) | ||
13 | |||
14 | const 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. | ||
21 | func unsafeRetrieveField(v reflect.Value, f reflect.StructField) reflect.Value { | ||
22 | return reflect.NewAt(f.Type, unsafe.Pointer(v.UnsafeAddr()+f.Offset)).Elem() | ||
23 | } | ||