jxyowen 7 anos atrás
pai
commit
06fdc4e77f
100 arquivos alterados com 12011 adições e 66 exclusões
  1. 1 0
      .gitignore
  2. 20 5
      glide.lock
  3. 1 1
      glide.yaml
  4. 14 0
      vendor/github.com/davecgh/go-spew/.travis.yml
  5. 15 0
      vendor/github.com/davecgh/go-spew/LICENSE
  6. 194 0
      vendor/github.com/davecgh/go-spew/README.md
  7. 22 0
      vendor/github.com/davecgh/go-spew/cov_report.sh
  8. 152 0
      vendor/github.com/davecgh/go-spew/spew/bypass.go
  9. 38 0
      vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
  10. 341 0
      vendor/github.com/davecgh/go-spew/spew/common.go
  11. 298 0
      vendor/github.com/davecgh/go-spew/spew/common_test.go
  12. 297 0
      vendor/github.com/davecgh/go-spew/spew/config.go
  13. 202 0
      vendor/github.com/davecgh/go-spew/spew/doc.go
  14. 509 0
      vendor/github.com/davecgh/go-spew/spew/dump.go
  15. 1042 0
      vendor/github.com/davecgh/go-spew/spew/dump_test.go
  16. 99 0
      vendor/github.com/davecgh/go-spew/spew/dumpcgo_test.go
  17. 26 0
      vendor/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
  18. 226 0
      vendor/github.com/davecgh/go-spew/spew/example_test.go
  19. 419 0
      vendor/github.com/davecgh/go-spew/spew/format.go
  20. 1558 0
      vendor/github.com/davecgh/go-spew/spew/format_test.go
  21. 87 0
      vendor/github.com/davecgh/go-spew/spew/internal_test.go
  22. 102 0
      vendor/github.com/davecgh/go-spew/spew/internalunsafe_test.go
  23. 148 0
      vendor/github.com/davecgh/go-spew/spew/spew.go
  24. 309 0
      vendor/github.com/davecgh/go-spew/spew/spew_test.go
  25. 82 0
      vendor/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go
  26. 61 0
      vendor/github.com/davecgh/go-spew/test_coverage.txt
  27. 96 0
      vendor/github.com/jmespath/go-jmespath/compliance/basic.json
  28. 257 0
      vendor/github.com/jmespath/go-jmespath/compliance/boolean.json
  29. 25 0
      vendor/github.com/jmespath/go-jmespath/compliance/current.json
  30. 46 0
      vendor/github.com/jmespath/go-jmespath/compliance/escape.json
  31. 468 0
      vendor/github.com/jmespath/go-jmespath/compliance/filters.json
  32. 825 0
      vendor/github.com/jmespath/go-jmespath/compliance/functions.json
  33. 1377 0
      vendor/github.com/jmespath/go-jmespath/compliance/identifiers.json
  34. 346 0
      vendor/github.com/jmespath/go-jmespath/compliance/indices.json
  35. 185 0
      vendor/github.com/jmespath/go-jmespath/compliance/literal.json
  36. 393 0
      vendor/github.com/jmespath/go-jmespath/compliance/multiselect.json
  37. 59 0
      vendor/github.com/jmespath/go-jmespath/compliance/ormatch.json
  38. 131 0
      vendor/github.com/jmespath/go-jmespath/compliance/pipe.json
  39. 187 0
      vendor/github.com/jmespath/go-jmespath/compliance/slice.json
  40. 616 0
      vendor/github.com/jmespath/go-jmespath/compliance/syntax.json
  41. 38 0
      vendor/github.com/jmespath/go-jmespath/compliance/unicode.json
  42. 460 0
      vendor/github.com/jmespath/go-jmespath/compliance/wildcard.json
  43. 123 0
      vendor/github.com/jmespath/go-jmespath/compliance_test.go
  44. 60 60
      vendor/github.com/jmespath/go-jmespath/functions.go
  45. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-1
  46. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-10
  47. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-100
  48. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-101
  49. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-102
  50. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-103
  51. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-104
  52. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-105
  53. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-106
  54. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-107
  55. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-108
  56. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-109
  57. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-110
  58. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-112
  59. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-115
  60. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-118
  61. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-119
  62. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-12
  63. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-120
  64. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-121
  65. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-122
  66. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-123
  67. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-126
  68. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-128
  69. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-129
  70. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-13
  71. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-130
  72. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-131
  73. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-132
  74. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-133
  75. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-134
  76. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-135
  77. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-136
  78. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-137
  79. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-138
  80. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-139
  81. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-14
  82. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-140
  83. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-141
  84. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-142
  85. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-143
  86. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-144
  87. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-145
  88. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-146
  89. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-147
  90. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-148
  91. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-149
  92. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-15
  93. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-150
  94. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-151
  95. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-152
  96. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-153
  97. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-155
  98. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-156
  99. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-157
  100. 1 0
      vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-158

+ 1 - 0
.gitignore

@@ -10,3 +10,4 @@ workspace.xml
 build/
 dist/
 out/
+.gitignore

+ 20 - 5
glide.lock

@@ -1,12 +1,27 @@
-hash: 8c102e206e59c5696ee34277c9480202d776b65781cad393a25087d83966e4f3
-updated: 2018-01-10T11:08:35.178977776+08:00
+hash: 2c53e3f15b3c2f22416b57a3202f6aee22b6c77728564536f5a76104070b2d2a
+updated: 2018-04-16T20:50:37.518986312+08:00
 imports:
 - name: github.com/jmespath/go-jmespath
   version: 3433f3ea46d9f8019119e7dd41274e112a2359a9
 - name: github.com/json-iterator/go
-  version: f7279a603edee96fe7764d3de9c6ff8cf9970994
+  version: ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4
+- name: github.com/modern-go/concurrent
+  version: bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94
+- name: github.com/modern-go/reflect2
+  version: 05fbef0ca5da472bbf96c9322b84a53edc03c9fd
 - name: github.com/satori/go.uuid
-  version: 879c5887cd475cd7864858769793b2ceb0d44feb
+  version: f58768cc1a7a7e77a3bd49e98cdd21419399b6a3
+- name: github.com/sirupsen/logrus
+  version: c155da19408a8799da419ed3eeb0cb5db0ad5dbc
+- name: golang.org/x/crypto
+  version: d6449816ce06963d9d136eee5a56fca5b0616e7e
+  subpackages:
+  - ssh/terminal
+- name: golang.org/x/sys
+  version: 2f57af4873d00d535c5c9028850aa2152e6a5566
+  subpackages:
+  - unix
+  - windows
 testImports:
 - name: github.com/davecgh/go-spew
   version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
@@ -17,6 +32,6 @@ testImports:
   subpackages:
   - difflib
 - name: github.com/stretchr/testify
-  version: b91bfb9ebec76498946beb6af7c0230c7cc7ba6c
+  version: 12b6f73e6084dad08a7c6e575284b177ecafbc71
   subpackages:
   - assert

+ 1 - 1
glide.yaml

@@ -9,7 +9,7 @@ import:
 - package: github.com/json-iterator/go
   version: ^1.0.4
 - package: github.com/sirupsen/logrus
-
+  version: ^1.0.5
 testImport:
 - package: github.com/stretchr/testify
   version: ^1.1.4

+ 14 - 0
vendor/github.com/davecgh/go-spew/.travis.yml

@@ -0,0 +1,14 @@
+language: go
+go:
+    - 1.5.4
+    - 1.6.3
+    - 1.7
+install:
+    - go get -v golang.org/x/tools/cmd/cover
+script:
+    - go test -v -tags=safe ./spew
+    - go test -v -tags=testcgo ./spew -covermode=count -coverprofile=profile.cov
+after_success:
+    - go get -v github.com/mattn/goveralls
+    - export PATH=$PATH:$HOME/gopath/bin
+    - goveralls -coverprofile=profile.cov -service=travis-ci

+ 15 - 0
vendor/github.com/davecgh/go-spew/LICENSE

@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 194 - 0
vendor/github.com/davecgh/go-spew/README.md

@@ -0,0 +1,194 @@
+go-spew
+=======
+
+[![Build Status](https://travis-ci.org/davecgh/go-spew.png?branch=master)]
+(https://travis-ci.org/davecgh/go-spew) [![Coverage Status]
+(https://coveralls.io/repos/davecgh/go-spew/badge.png?branch=master)]
+(https://coveralls.io/r/davecgh/go-spew?branch=master)
+
+Go-spew implements a deep pretty printer for Go data structures to aid in
+debugging.  A comprehensive suite of tests with 100% test coverage is provided
+to ensure proper functionality.  See `test_coverage.txt` for the gocov coverage
+report.  Go-spew is licensed under the liberal ISC license, so it may be used in
+open source or commercial projects.
+
+If you're interested in reading about how this package came to life and some
+of the challenges involved in providing a deep pretty printer, there is a blog
+post about it
+[here](https://web.archive.org/web/20160304013555/https://blog.cyphertite.com/go-spew-a-journey-into-dumping-go-data-structures/).
+
+## Documentation
+
+[![GoDoc](https://godoc.org/github.com/davecgh/go-spew/spew?status.png)]
+(http://godoc.org/github.com/davecgh/go-spew/spew)
+
+Full `go doc` style documentation for the project can be viewed online without
+installing this package by using the excellent GoDoc site here:
+http://godoc.org/github.com/davecgh/go-spew/spew
+
+You can also view the documentation locally once the package is installed with
+the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to
+http://localhost:6060/pkg/github.com/davecgh/go-spew/spew
+
+## Installation
+
+```bash
+$ go get -u github.com/davecgh/go-spew/spew
+```
+
+## Quick Start
+
+Add this import line to the file you're working in:
+
+```Go
+import "github.com/davecgh/go-spew/spew"
+```
+
+To dump a variable with full newlines, indentation, type, and pointer
+information use Dump, Fdump, or Sdump:
+
+```Go
+spew.Dump(myVar1, myVar2, ...)
+spew.Fdump(someWriter, myVar1, myVar2, ...)
+str := spew.Sdump(myVar1, myVar2, ...)
+```
+
+Alternatively, if you would prefer to use format strings with a compacted inline
+printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most
+compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types
+and pointer addresses): 
+
+```Go
+spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+```
+
+## Debugging a Web Application Example
+
+Here is an example of how you can use `spew.Sdump()` to help debug a web application. Please be sure to wrap your output using the `html.EscapeString()` function for safety reasons. You should also only use this debugging technique in a development environment, never in production.
+
+```Go
+package main
+
+import (
+    "fmt"
+    "html"
+    "net/http"
+
+    "github.com/davecgh/go-spew/spew"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+    w.Header().Set("Content-Type", "text/html")
+    fmt.Fprintf(w, "Hi there, %s!", r.URL.Path[1:])
+    fmt.Fprintf(w, "<!--\n" + html.EscapeString(spew.Sdump(w)) + "\n-->")
+}
+
+func main() {
+    http.HandleFunc("/", handler)
+    http.ListenAndServe(":8080", nil)
+}
+```
+
+## Sample Dump Output
+
+```
+(main.Foo) {
+ unexportedField: (*main.Bar)(0xf84002e210)({
+  flag: (main.Flag) flagTwo,
+  data: (uintptr) <nil>
+ }),
+ ExportedField: (map[interface {}]interface {}) {
+  (string) "one": (bool) true
+ }
+}
+([]uint8) {
+ 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20  |............... |
+ 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!"#$%&'()*+,-./0|
+ 00000020  31 32                                             |12|
+}
+```
+
+## Sample Formatter Output
+
+Double pointer to a uint8:
+```
+	  %v: <**>5
+	 %+v: <**>(0xf8400420d0->0xf8400420c8)5
+	 %#v: (**uint8)5
+	%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
+```
+
+Pointer to circular struct with a uint8 field and a pointer to itself:
+```
+	  %v: <*>{1 <*><shown>}
+	 %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
+	 %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
+	%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
+```
+
+## Configuration Options
+
+Configuration of spew is handled by fields in the ConfigState type. For
+convenience, all of the top-level functions use a global state available via the
+spew.Config global.
+
+It is also possible to create a ConfigState instance that provides methods
+equivalent to the top-level functions. This allows concurrent configuration
+options. See the ConfigState documentation for more details.
+
+```
+* Indent
+	String to use for each indentation level for Dump functions.
+	It is a single space by default.  A popular alternative is "\t".
+
+* MaxDepth
+	Maximum number of levels to descend into nested data structures.
+	There is no limit by default.
+
+* DisableMethods
+	Disables invocation of error and Stringer interface methods.
+	Method invocation is enabled by default.
+
+* DisablePointerMethods
+	Disables invocation of error and Stringer interface methods on types
+	which only accept pointer receivers from non-pointer variables.  This option
+	relies on access to the unsafe package, so it will not have any effect when
+	running in environments without access to the unsafe package such as Google
+	App Engine or with the "safe" build tag specified.
+	Pointer method invocation is enabled by default.
+
+* ContinueOnMethod
+	Enables recursion into types after invoking error and Stringer interface
+	methods. Recursion after method invocation is disabled by default.
+
+* SortKeys
+	Specifies map keys should be sorted before being printed. Use
+	this to have a more deterministic, diffable output.  Note that
+	only native types (bool, int, uint, floats, uintptr and string)
+	and types which implement error or Stringer interfaces are supported,
+	with other types sorted according to the reflect.Value.String() output
+	which guarantees display stability.  Natural map order is used by
+	default.
+
+* SpewKeys
+	SpewKeys specifies that, as a last resort attempt, map keys should be
+	spewed to strings and sorted by those strings.  This is only considered
+	if SortKeys is true.
+
+```
+
+## Unsafe Package Dependency
+
+This package relies on the unsafe package to perform some of the more advanced
+features, however it also supports a "limited" mode which allows it to work in
+environments where the unsafe package is not available.  By default, it will
+operate in this mode on Google App Engine and when compiled with GopherJS.  The
+"safe" build tag may also be specified to force the package to build without
+using the unsafe package.
+
+## License
+
+Go-spew is licensed under the liberal ISC License.

+ 22 - 0
vendor/github.com/davecgh/go-spew/cov_report.sh

@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# This script uses gocov to generate a test coverage report.
+# The gocov tool my be obtained with the following command:
+#   go get github.com/axw/gocov/gocov
+#
+# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH.
+
+# Check for gocov.
+if ! type gocov >/dev/null 2>&1; then
+	echo >&2 "This script requires the gocov tool."
+	echo >&2 "You may obtain it with the following command:"
+	echo >&2 "go get github.com/axw/gocov/gocov"
+	exit 1
+fi
+
+# Only run the cgo tests if gcc is installed.
+if type gcc >/dev/null 2>&1; then
+	(cd spew && gocov test -tags testcgo | gocov report)
+else
+	(cd spew && gocov test | gocov report)
+fi

+ 152 - 0
vendor/github.com/davecgh/go-spew/spew/bypass.go

@@ -0,0 +1,152 @@
+// Copyright (c) 2015 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is not running on Google App Engine, compiled by GopherJS, and
+// "-tags safe" is not added to the go build command line.  The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build !js,!appengine,!safe,!disableunsafe
+
+package spew
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+const (
+	// UnsafeDisabled is a build-time constant which specifies whether or
+	// not access to the unsafe package is available.
+	UnsafeDisabled = false
+
+	// ptrSize is the size of a pointer on the current arch.
+	ptrSize = unsafe.Sizeof((*byte)(nil))
+)
+
+var (
+	// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
+	// internal reflect.Value fields.  These values are valid before golang
+	// commit ecccf07e7f9d which changed the format.  The are also valid
+	// after commit 82f48826c6c7 which changed the format again to mirror
+	// the original format.  Code in the init function updates these offsets
+	// as necessary.
+	offsetPtr    = uintptr(ptrSize)
+	offsetScalar = uintptr(0)
+	offsetFlag   = uintptr(ptrSize * 2)
+
+	// flagKindWidth and flagKindShift indicate various bits that the
+	// reflect package uses internally to track kind information.
+	//
+	// flagRO indicates whether or not the value field of a reflect.Value is
+	// read-only.
+	//
+	// flagIndir indicates whether the value field of a reflect.Value is
+	// the actual data or a pointer to the data.
+	//
+	// These values are valid before golang commit 90a7c3c86944 which
+	// changed their positions.  Code in the init function updates these
+	// flags as necessary.
+	flagKindWidth = uintptr(5)
+	flagKindShift = uintptr(flagKindWidth - 1)
+	flagRO        = uintptr(1 << 0)
+	flagIndir     = uintptr(1 << 1)
+)
+
+func init() {
+	// Older versions of reflect.Value stored small integers directly in the
+	// ptr field (which is named val in the older versions).  Versions
+	// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
+	// scalar for this purpose which unfortunately came before the flag
+	// field, so the offset of the flag field is different for those
+	// versions.
+	//
+	// This code constructs a new reflect.Value from a known small integer
+	// and checks if the size of the reflect.Value struct indicates it has
+	// the scalar field. When it does, the offsets are updated accordingly.
+	vv := reflect.ValueOf(0xf00)
+	if unsafe.Sizeof(vv) == (ptrSize * 4) {
+		offsetScalar = ptrSize * 2
+		offsetFlag = ptrSize * 3
+	}
+
+	// Commit 90a7c3c86944 changed the flag positions such that the low
+	// order bits are the kind.  This code extracts the kind from the flags
+	// field and ensures it's the correct type.  When it's not, the flag
+	// order has been changed to the newer format, so the flags are updated
+	// accordingly.
+	upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
+	upfv := *(*uintptr)(upf)
+	flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
+	if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
+		flagKindShift = 0
+		flagRO = 1 << 5
+		flagIndir = 1 << 6
+
+		// Commit adf9b30e5594 modified the flags to separate the
+		// flagRO flag into two bits which specifies whether or not the
+		// field is embedded.  This causes flagIndir to move over a bit
+		// and means that flagRO is the combination of either of the
+		// original flagRO bit and the new bit.
+		//
+		// This code detects the change by extracting what used to be
+		// the indirect bit to ensure it's set.  When it's not, the flag
+		// order has been changed to the newer format, so the flags are
+		// updated accordingly.
+		if upfv&flagIndir == 0 {
+			flagRO = 3 << 5
+			flagIndir = 1 << 7
+		}
+	}
+}
+
+// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
+// the typical safety restrictions preventing access to unaddressable and
+// unexported data.  It works by digging the raw pointer to the underlying
+// value out of the protected value and generating a new unprotected (unsafe)
+// reflect.Value to it.
+//
+// This allows us to check for implementations of the Stringer and error
+// interfaces to be used for pretty printing ordinarily unaddressable and
+// inaccessible values such as unexported struct fields.
+func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
+	indirects := 1
+	vt := v.Type()
+	upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
+	rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
+	if rvf&flagIndir != 0 {
+		vt = reflect.PtrTo(v.Type())
+		indirects++
+	} else if offsetScalar != 0 {
+		// The value is in the scalar field when it's not one of the
+		// reference types.
+		switch vt.Kind() {
+		case reflect.Uintptr:
+		case reflect.Chan:
+		case reflect.Func:
+		case reflect.Map:
+		case reflect.Ptr:
+		case reflect.UnsafePointer:
+		default:
+			upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
+				offsetScalar)
+		}
+	}
+
+	pv := reflect.NewAt(vt, upv)
+	rv = pv
+	for i := 0; i < indirects; i++ {
+		rv = rv.Elem()
+	}
+	return rv
+}

+ 38 - 0
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go

@@ -0,0 +1,38 @@
+// Copyright (c) 2015 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is running on Google App Engine, compiled by GopherJS, or
+// "-tags safe" is added to the go build command line.  The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build js appengine safe disableunsafe
+
+package spew
+
+import "reflect"
+
+const (
+	// UnsafeDisabled is a build-time constant which specifies whether or
+	// not access to the unsafe package is available.
+	UnsafeDisabled = true
+)
+
+// unsafeReflectValue typically converts the passed reflect.Value into a one
+// that bypasses the typical safety restrictions preventing access to
+// unaddressable and unexported data.  However, doing this relies on access to
+// the unsafe package.  This is a stub version which simply returns the passed
+// reflect.Value when the unsafe package is not available.
+func unsafeReflectValue(v reflect.Value) reflect.Value {
+	return v
+}

+ 341 - 0
vendor/github.com/davecgh/go-spew/spew/common.go

@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"reflect"
+	"sort"
+	"strconv"
+)
+
+// Some constants in the form of bytes to avoid string overhead.  This mirrors
+// the technique used in the fmt package.
+var (
+	panicBytes            = []byte("(PANIC=")
+	plusBytes             = []byte("+")
+	iBytes                = []byte("i")
+	trueBytes             = []byte("true")
+	falseBytes            = []byte("false")
+	interfaceBytes        = []byte("(interface {})")
+	commaNewlineBytes     = []byte(",\n")
+	newlineBytes          = []byte("\n")
+	openBraceBytes        = []byte("{")
+	openBraceNewlineBytes = []byte("{\n")
+	closeBraceBytes       = []byte("}")
+	asteriskBytes         = []byte("*")
+	colonBytes            = []byte(":")
+	colonSpaceBytes       = []byte(": ")
+	openParenBytes        = []byte("(")
+	closeParenBytes       = []byte(")")
+	spaceBytes            = []byte(" ")
+	pointerChainBytes     = []byte("->")
+	nilAngleBytes         = []byte("<nil>")
+	maxNewlineBytes       = []byte("<max depth reached>\n")
+	maxShortBytes         = []byte("<max>")
+	circularBytes         = []byte("<already shown>")
+	circularShortBytes    = []byte("<shown>")
+	invalidAngleBytes     = []byte("<invalid>")
+	openBracketBytes      = []byte("[")
+	closeBracketBytes     = []byte("]")
+	percentBytes          = []byte("%")
+	precisionBytes        = []byte(".")
+	openAngleBytes        = []byte("<")
+	closeAngleBytes       = []byte(">")
+	openMapBytes          = []byte("map[")
+	closeMapBytes         = []byte("]")
+	lenEqualsBytes        = []byte("len=")
+	capEqualsBytes        = []byte("cap=")
+)
+
+// hexDigits is used to map a decimal value to a hex digit.
+var hexDigits = "0123456789abcdef"
+
+// catchPanic handles any panics that might occur during the handleMethods
+// calls.
+func catchPanic(w io.Writer, v reflect.Value) {
+	if err := recover(); err != nil {
+		w.Write(panicBytes)
+		fmt.Fprintf(w, "%v", err)
+		w.Write(closeParenBytes)
+	}
+}
+
+// handleMethods attempts to call the Error and String methods on the underlying
+// type the passed reflect.Value represents and outputes the result to Writer w.
+//
+// It handles panics in any called methods by catching and displaying the error
+// as the formatted value.
+func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
+	// We need an interface to check if the type implements the error or
+	// Stringer interface.  However, the reflect package won't give us an
+	// interface on certain things like unexported struct fields in order
+	// to enforce visibility rules.  We use unsafe, when it's available,
+	// to bypass these restrictions since this package does not mutate the
+	// values.
+	if !v.CanInterface() {
+		if UnsafeDisabled {
+			return false
+		}
+
+		v = unsafeReflectValue(v)
+	}
+
+	// Choose whether or not to do error and Stringer interface lookups against
+	// the base type or a pointer to the base type depending on settings.
+	// Technically calling one of these methods with a pointer receiver can
+	// mutate the value, however, types which choose to satisify an error or
+	// Stringer interface with a pointer receiver should not be mutating their
+	// state inside these interface methods.
+	if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
+		v = unsafeReflectValue(v)
+	}
+	if v.CanAddr() {
+		v = v.Addr()
+	}
+
+	// Is it an error or Stringer?
+	switch iface := v.Interface().(type) {
+	case error:
+		defer catchPanic(w, v)
+		if cs.ContinueOnMethod {
+			w.Write(openParenBytes)
+			w.Write([]byte(iface.Error()))
+			w.Write(closeParenBytes)
+			w.Write(spaceBytes)
+			return false
+		}
+
+		w.Write([]byte(iface.Error()))
+		return true
+
+	case fmt.Stringer:
+		defer catchPanic(w, v)
+		if cs.ContinueOnMethod {
+			w.Write(openParenBytes)
+			w.Write([]byte(iface.String()))
+			w.Write(closeParenBytes)
+			w.Write(spaceBytes)
+			return false
+		}
+		w.Write([]byte(iface.String()))
+		return true
+	}
+	return false
+}
+
+// printBool outputs a boolean value as true or false to Writer w.
+func printBool(w io.Writer, val bool) {
+	if val {
+		w.Write(trueBytes)
+	} else {
+		w.Write(falseBytes)
+	}
+}
+
+// printInt outputs a signed integer value to Writer w.
+func printInt(w io.Writer, val int64, base int) {
+	w.Write([]byte(strconv.FormatInt(val, base)))
+}
+
+// printUint outputs an unsigned integer value to Writer w.
+func printUint(w io.Writer, val uint64, base int) {
+	w.Write([]byte(strconv.FormatUint(val, base)))
+}
+
+// printFloat outputs a floating point value using the specified precision,
+// which is expected to be 32 or 64bit, to Writer w.
+func printFloat(w io.Writer, val float64, precision int) {
+	w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
+}
+
+// printComplex outputs a complex value using the specified float precision
+// for the real and imaginary parts to Writer w.
+func printComplex(w io.Writer, c complex128, floatPrecision int) {
+	r := real(c)
+	w.Write(openParenBytes)
+	w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
+	i := imag(c)
+	if i >= 0 {
+		w.Write(plusBytes)
+	}
+	w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
+	w.Write(iBytes)
+	w.Write(closeParenBytes)
+}
+
+// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
+// prefix to Writer w.
+func printHexPtr(w io.Writer, p uintptr) {
+	// Null pointer.
+	num := uint64(p)
+	if num == 0 {
+		w.Write(nilAngleBytes)
+		return
+	}
+
+	// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
+	buf := make([]byte, 18)
+
+	// It's simpler to construct the hex string right to left.
+	base := uint64(16)
+	i := len(buf) - 1
+	for num >= base {
+		buf[i] = hexDigits[num%base]
+		num /= base
+		i--
+	}
+	buf[i] = hexDigits[num]
+
+	// Add '0x' prefix.
+	i--
+	buf[i] = 'x'
+	i--
+	buf[i] = '0'
+
+	// Strip unused leading bytes.
+	buf = buf[i:]
+	w.Write(buf)
+}
+
+// valuesSorter implements sort.Interface to allow a slice of reflect.Value
+// elements to be sorted.
+type valuesSorter struct {
+	values  []reflect.Value
+	strings []string // either nil or same len and values
+	cs      *ConfigState
+}
+
+// newValuesSorter initializes a valuesSorter instance, which holds a set of
+// surrogate keys on which the data should be sorted.  It uses flags in
+// ConfigState to decide if and how to populate those surrogate keys.
+func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
+	vs := &valuesSorter{values: values, cs: cs}
+	if canSortSimply(vs.values[0].Kind()) {
+		return vs
+	}
+	if !cs.DisableMethods {
+		vs.strings = make([]string, len(values))
+		for i := range vs.values {
+			b := bytes.Buffer{}
+			if !handleMethods(cs, &b, vs.values[i]) {
+				vs.strings = nil
+				break
+			}
+			vs.strings[i] = b.String()
+		}
+	}
+	if vs.strings == nil && cs.SpewKeys {
+		vs.strings = make([]string, len(values))
+		for i := range vs.values {
+			vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
+		}
+	}
+	return vs
+}
+
+// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
+// directly, or whether it should be considered for sorting by surrogate keys
+// (if the ConfigState allows it).
+func canSortSimply(kind reflect.Kind) bool {
+	// This switch parallels valueSortLess, except for the default case.
+	switch kind {
+	case reflect.Bool:
+		return true
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+		return true
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+		return true
+	case reflect.Float32, reflect.Float64:
+		return true
+	case reflect.String:
+		return true
+	case reflect.Uintptr:
+		return true
+	case reflect.Array:
+		return true
+	}
+	return false
+}
+
+// Len returns the number of values in the slice.  It is part of the
+// sort.Interface implementation.
+func (s *valuesSorter) Len() int {
+	return len(s.values)
+}
+
+// Swap swaps the values at the passed indices.  It is part of the
+// sort.Interface implementation.
+func (s *valuesSorter) Swap(i, j int) {
+	s.values[i], s.values[j] = s.values[j], s.values[i]
+	if s.strings != nil {
+		s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
+	}
+}
+
+// valueSortLess returns whether the first value should sort before the second
+// value.  It is used by valueSorter.Less as part of the sort.Interface
+// implementation.
+func valueSortLess(a, b reflect.Value) bool {
+	switch a.Kind() {
+	case reflect.Bool:
+		return !a.Bool() && b.Bool()
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+		return a.Int() < b.Int()
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+		return a.Uint() < b.Uint()
+	case reflect.Float32, reflect.Float64:
+		return a.Float() < b.Float()
+	case reflect.String:
+		return a.String() < b.String()
+	case reflect.Uintptr:
+		return a.Uint() < b.Uint()
+	case reflect.Array:
+		// Compare the contents of both arrays.
+		l := a.Len()
+		for i := 0; i < l; i++ {
+			av := a.Index(i)
+			bv := b.Index(i)
+			if av.Interface() == bv.Interface() {
+				continue
+			}
+			return valueSortLess(av, bv)
+		}
+	}
+	return a.String() < b.String()
+}
+
+// Less returns whether the value at index i should sort before the
+// value at index j.  It is part of the sort.Interface implementation.
+func (s *valuesSorter) Less(i, j int) bool {
+	if s.strings == nil {
+		return valueSortLess(s.values[i], s.values[j])
+	}
+	return s.strings[i] < s.strings[j]
+}
+
+// sortValues is a sort function that handles both native types and any type that
+// can be converted to error or Stringer.  Other inputs are sorted according to
+// their Value.String() value to ensure display stability.
+func sortValues(values []reflect.Value, cs *ConfigState) {
+	if len(values) == 0 {
+		return
+	}
+	sort.Sort(newValuesSorter(values, cs))
+}

+ 298 - 0
vendor/github.com/davecgh/go-spew/spew/common_test.go

@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew_test
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+
+	"github.com/davecgh/go-spew/spew"
+)
+
+// custom type to test Stinger interface on non-pointer receiver.
+type stringer string
+
+// String implements the Stringer interface for testing invocation of custom
+// stringers on types with non-pointer receivers.
+func (s stringer) String() string {
+	return "stringer " + string(s)
+}
+
+// custom type to test Stinger interface on pointer receiver.
+type pstringer string
+
+// String implements the Stringer interface for testing invocation of custom
+// stringers on types with only pointer receivers.
+func (s *pstringer) String() string {
+	return "stringer " + string(*s)
+}
+
+// xref1 and xref2 are cross referencing structs for testing circular reference
+// detection.
+type xref1 struct {
+	ps2 *xref2
+}
+type xref2 struct {
+	ps1 *xref1
+}
+
+// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
+// reference for testing detection.
+type indirCir1 struct {
+	ps2 *indirCir2
+}
+type indirCir2 struct {
+	ps3 *indirCir3
+}
+type indirCir3 struct {
+	ps1 *indirCir1
+}
+
+// embed is used to test embedded structures.
+type embed struct {
+	a string
+}
+
+// embedwrap is used to test embedded structures.
+type embedwrap struct {
+	*embed
+	e *embed
+}
+
+// panicer is used to intentionally cause a panic for testing spew properly
+// handles them
+type panicer int
+
+func (p panicer) String() string {
+	panic("test panic")
+}
+
+// customError is used to test custom error interface invocation.
+type customError int
+
+func (e customError) Error() string {
+	return fmt.Sprintf("error: %d", int(e))
+}
+
+// stringizeWants converts a slice of wanted test output into a format suitable
+// for a test error message.
+func stringizeWants(wants []string) string {
+	s := ""
+	for i, want := range wants {
+		if i > 0 {
+			s += fmt.Sprintf("want%d: %s", i+1, want)
+		} else {
+			s += "want: " + want
+		}
+	}
+	return s
+}
+
+// testFailed returns whether or not a test failed by checking if the result
+// of the test is in the slice of wanted strings.
+func testFailed(result string, wants []string) bool {
+	for _, want := range wants {
+		if result == want {
+			return false
+		}
+	}
+	return true
+}
+
+type sortableStruct struct {
+	x int
+}
+
+func (ss sortableStruct) String() string {
+	return fmt.Sprintf("ss.%d", ss.x)
+}
+
+type unsortableStruct struct {
+	x int
+}
+
+type sortTestCase struct {
+	input    []reflect.Value
+	expected []reflect.Value
+}
+
+func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) {
+	getInterfaces := func(values []reflect.Value) []interface{} {
+		interfaces := []interface{}{}
+		for _, v := range values {
+			interfaces = append(interfaces, v.Interface())
+		}
+		return interfaces
+	}
+
+	for _, test := range tests {
+		spew.SortValues(test.input, cs)
+		// reflect.DeepEqual cannot really make sense of reflect.Value,
+		// probably because of all the pointer tricks. For instance,
+		// v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{}
+		// instead.
+		input := getInterfaces(test.input)
+		expected := getInterfaces(test.expected)
+		if !reflect.DeepEqual(input, expected) {
+			t.Errorf("Sort mismatch:\n %v != %v", input, expected)
+		}
+	}
+}
+
+// TestSortValues ensures the sort functionality for relect.Value based sorting
+// works as intended.
+func TestSortValues(t *testing.T) {
+	v := reflect.ValueOf
+
+	a := v("a")
+	b := v("b")
+	c := v("c")
+	embedA := v(embed{"a"})
+	embedB := v(embed{"b"})
+	embedC := v(embed{"c"})
+	tests := []sortTestCase{
+		// No values.
+		{
+			[]reflect.Value{},
+			[]reflect.Value{},
+		},
+		// Bools.
+		{
+			[]reflect.Value{v(false), v(true), v(false)},
+			[]reflect.Value{v(false), v(false), v(true)},
+		},
+		// Ints.
+		{
+			[]reflect.Value{v(2), v(1), v(3)},
+			[]reflect.Value{v(1), v(2), v(3)},
+		},
+		// Uints.
+		{
+			[]reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
+			[]reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
+		},
+		// Floats.
+		{
+			[]reflect.Value{v(2.0), v(1.0), v(3.0)},
+			[]reflect.Value{v(1.0), v(2.0), v(3.0)},
+		},
+		// Strings.
+		{
+			[]reflect.Value{b, a, c},
+			[]reflect.Value{a, b, c},
+		},
+		// Array
+		{
+			[]reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})},
+			[]reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})},
+		},
+		// Uintptrs.
+		{
+			[]reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
+			[]reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
+		},
+		// SortableStructs.
+		{
+			// Note: not sorted - DisableMethods is set.
+			[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
+			[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
+		},
+		// UnsortableStructs.
+		{
+			// Note: not sorted - SpewKeys is false.
+			[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
+			[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
+		},
+		// Invalid.
+		{
+			[]reflect.Value{embedB, embedA, embedC},
+			[]reflect.Value{embedB, embedA, embedC},
+		},
+	}
+	cs := spew.ConfigState{DisableMethods: true, SpewKeys: false}
+	helpTestSortValues(tests, &cs, t)
+}
+
+// TestSortValuesWithMethods ensures the sort functionality for relect.Value
+// based sorting works as intended when using string methods.
+func TestSortValuesWithMethods(t *testing.T) {
+	v := reflect.ValueOf
+
+	a := v("a")
+	b := v("b")
+	c := v("c")
+	tests := []sortTestCase{
+		// Ints.
+		{
+			[]reflect.Value{v(2), v(1), v(3)},
+			[]reflect.Value{v(1), v(2), v(3)},
+		},
+		// Strings.
+		{
+			[]reflect.Value{b, a, c},
+			[]reflect.Value{a, b, c},
+		},
+		// SortableStructs.
+		{
+			[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
+			[]reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
+		},
+		// UnsortableStructs.
+		{
+			// Note: not sorted - SpewKeys is false.
+			[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
+			[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
+		},
+	}
+	cs := spew.ConfigState{DisableMethods: false, SpewKeys: false}
+	helpTestSortValues(tests, &cs, t)
+}
+
+// TestSortValuesWithSpew ensures the sort functionality for relect.Value
+// based sorting works as intended when using spew to stringify keys.
+func TestSortValuesWithSpew(t *testing.T) {
+	v := reflect.ValueOf
+
+	a := v("a")
+	b := v("b")
+	c := v("c")
+	tests := []sortTestCase{
+		// Ints.
+		{
+			[]reflect.Value{v(2), v(1), v(3)},
+			[]reflect.Value{v(1), v(2), v(3)},
+		},
+		// Strings.
+		{
+			[]reflect.Value{b, a, c},
+			[]reflect.Value{a, b, c},
+		},
+		// SortableStructs.
+		{
+			[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
+			[]reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
+		},
+		// UnsortableStructs.
+		{
+			[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
+			[]reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})},
+		},
+	}
+	cs := spew.ConfigState{DisableMethods: true, SpewKeys: true}
+	helpTestSortValues(tests, &cs, t)
+}

+ 297 - 0
vendor/github.com/davecgh/go-spew/spew/config.go

@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+)
+
+// ConfigState houses the configuration options used by spew to format and
+// display values.  There is a global instance, Config, that is used to control
+// all top-level Formatter and Dump functionality.  Each ConfigState instance
+// provides methods equivalent to the top-level functions.
+//
+// The zero value for ConfigState provides no indentation.  You would typically
+// want to set it to a space or a tab.
+//
+// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
+// with default settings.  See the documentation of NewDefaultConfig for default
+// values.
+type ConfigState struct {
+	// Indent specifies the string to use for each indentation level.  The
+	// global config instance that all top-level functions use set this to a
+	// single space by default.  If you would like more indentation, you might
+	// set this to a tab with "\t" or perhaps two spaces with "  ".
+	Indent string
+
+	// MaxDepth controls the maximum number of levels to descend into nested
+	// data structures.  The default, 0, means there is no limit.
+	//
+	// NOTE: Circular data structures are properly detected, so it is not
+	// necessary to set this value unless you specifically want to limit deeply
+	// nested data structures.
+	MaxDepth int
+
+	// DisableMethods specifies whether or not error and Stringer interfaces are
+	// invoked for types that implement them.
+	DisableMethods bool
+
+	// DisablePointerMethods specifies whether or not to check for and invoke
+	// error and Stringer interfaces on types which only accept a pointer
+	// receiver when the current type is not a pointer.
+	//
+	// NOTE: This might be an unsafe action since calling one of these methods
+	// with a pointer receiver could technically mutate the value, however,
+	// in practice, types which choose to satisify an error or Stringer
+	// interface with a pointer receiver should not be mutating their state
+	// inside these interface methods.  As a result, this option relies on
+	// access to the unsafe package, so it will not have any effect when
+	// running in environments without access to the unsafe package such as
+	// Google App Engine or with the "safe" build tag specified.
+	DisablePointerMethods bool
+
+	// ContinueOnMethod specifies whether or not recursion should continue once
+	// a custom error or Stringer interface is invoked.  The default, false,
+	// means it will print the results of invoking the custom error or Stringer
+	// interface and return immediately instead of continuing to recurse into
+	// the internals of the data type.
+	//
+	// NOTE: This flag does not have any effect if method invocation is disabled
+	// via the DisableMethods or DisablePointerMethods options.
+	ContinueOnMethod bool
+
+	// SortKeys specifies map keys should be sorted before being printed. Use
+	// this to have a more deterministic, diffable output.  Note that only
+	// native types (bool, int, uint, floats, uintptr and string) and types
+	// that support the error or Stringer interfaces (if methods are
+	// enabled) are supported, with other types sorted according to the
+	// reflect.Value.String() output which guarantees display stability.
+	SortKeys bool
+
+	// SpewKeys specifies that, as a last resort attempt, map keys should
+	// be spewed to strings and sorted by those strings.  This is only
+	// considered if SortKeys is true.
+	SpewKeys bool
+}
+
+// Config is the active configuration of the top-level functions.
+// The configuration can be changed by modifying the contents of spew.Config.
+var Config = ConfigState{Indent: " "}
+
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the formatted string as a value that satisfies error.  See NewFormatter
+// for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
+	return fmt.Errorf(format, c.convertArgs(a)...)
+}
+
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+	return fmt.Fprint(w, c.convertArgs(a)...)
+}
+
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+	return fmt.Fprintf(w, format, c.convertArgs(a)...)
+}
+
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
+// passed with a Formatter interface returned by c.NewFormatter.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+	return fmt.Fprintln(w, c.convertArgs(a)...)
+}
+
+// Print is a wrapper for fmt.Print that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
+	return fmt.Print(c.convertArgs(a)...)
+}
+
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
+	return fmt.Printf(format, c.convertArgs(a)...)
+}
+
+// Println is a wrapper for fmt.Println that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
+	return fmt.Println(c.convertArgs(a)...)
+}
+
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the resulting string.  See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprint(a ...interface{}) string {
+	return fmt.Sprint(c.convertArgs(a)...)
+}
+
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
+// the resulting string.  See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
+	return fmt.Sprintf(format, c.convertArgs(a)...)
+}
+
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
+// were passed with a Formatter interface returned by c.NewFormatter.  It
+// returns the resulting string.  See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
+func (c *ConfigState) Sprintln(a ...interface{}) string {
+	return fmt.Sprintln(c.convertArgs(a)...)
+}
+
+/*
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
+interface.  As a result, it integrates cleanly with standard fmt package
+printing functions.  The formatter is useful for inline printing of smaller data
+types similar to the standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
+combinations.  Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting.  In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Typically this function shouldn't be called directly.  It is much easier to make
+use of the custom formatter by calling one of the convenience functions such as
+c.Printf, c.Println, or c.Printf.
+*/
+func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
+	return newFormatter(c, v)
+}
+
+// Fdump formats and displays the passed arguments to io.Writer w.  It formats
+// exactly the same as Dump.
+func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
+	fdump(c, w, a...)
+}
+
+/*
+Dump displays the passed parameters to standard out with newlines, customizable
+indentation, and additional debug information such as complete types and all
+pointer addresses used to indirect to the final value.  It provides the
+following features over the built-in printing facilities provided by the fmt
+package:
+
+	* Pointers are dereferenced and followed
+	* Circular data structures are detected and handled properly
+	* Custom Stringer/error interfaces are optionally invoked, including
+	  on unexported types
+	* Custom types which only implement the Stringer/error interfaces via
+	  a pointer receiver are optionally invoked when passing non-pointer
+	  variables
+	* Byte arrays and slices are dumped like the hexdump -C command which
+	  includes offsets, byte values in hex, and ASCII output
+
+The configuration options are controlled by modifying the public members
+of c.  See ConfigState for options documentation.
+
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
+get the formatted result as a string.
+*/
+func (c *ConfigState) Dump(a ...interface{}) {
+	fdump(c, os.Stdout, a...)
+}
+
+// Sdump returns a string with the passed arguments formatted exactly the same
+// as Dump.
+func (c *ConfigState) Sdump(a ...interface{}) string {
+	var buf bytes.Buffer
+	fdump(c, &buf, a...)
+	return buf.String()
+}
+
+// convertArgs accepts a slice of arguments and returns a slice of the same
+// length with each argument converted to a spew Formatter interface using
+// the ConfigState associated with s.
+func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
+	formatters = make([]interface{}, len(args))
+	for index, arg := range args {
+		formatters[index] = newFormatter(c, arg)
+	}
+	return formatters
+}
+
+// NewDefaultConfig returns a ConfigState with the following default settings.
+//
+// 	Indent: " "
+// 	MaxDepth: 0
+// 	DisableMethods: false
+// 	DisablePointerMethods: false
+// 	ContinueOnMethod: false
+// 	SortKeys: false
+func NewDefaultConfig() *ConfigState {
+	return &ConfigState{Indent: " "}
+}

+ 202 - 0
vendor/github.com/davecgh/go-spew/spew/doc.go

@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Package spew implements a deep pretty printer for Go data structures to aid in
+debugging.
+
+A quick overview of the additional features spew provides over the built-in
+printing facilities for Go data types are as follows:
+
+	* Pointers are dereferenced and followed
+	* Circular data structures are detected and handled properly
+	* Custom Stringer/error interfaces are optionally invoked, including
+	  on unexported types
+	* Custom types which only implement the Stringer/error interfaces via
+	  a pointer receiver are optionally invoked when passing non-pointer
+	  variables
+	* Byte arrays and slices are dumped like the hexdump -C command which
+	  includes offsets, byte values in hex, and ASCII output (only when using
+	  Dump style)
+
+There are two different approaches spew allows for dumping Go data structures:
+
+	* Dump style which prints with newlines, customizable indentation,
+	  and additional debug information such as types and all pointer addresses
+	  used to indirect to the final value
+	* A custom Formatter interface that integrates cleanly with the standard fmt
+	  package and replaces %v, %+v, %#v, and %#+v to provide inline printing
+	  similar to the default %v while providing the additional functionality
+	  outlined above and passing unsupported format verbs such as %x and %q
+	  along to fmt
+
+Quick Start
+
+This section demonstrates how to quickly get started with spew.  See the
+sections below for further details on formatting and configuration options.
+
+To dump a variable with full newlines, indentation, type, and pointer
+information use Dump, Fdump, or Sdump:
+	spew.Dump(myVar1, myVar2, ...)
+	spew.Fdump(someWriter, myVar1, myVar2, ...)
+	str := spew.Sdump(myVar1, myVar2, ...)
+
+Alternatively, if you would prefer to use format strings with a compacted inline
+printing style, use the convenience wrappers Printf, Fprintf, etc with
+%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
+%#+v (adds types and pointer addresses):
+	spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+	spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+	spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+	spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+
+Configuration Options
+
+Configuration of spew is handled by fields in the ConfigState type.  For
+convenience, all of the top-level functions use a global state available
+via the spew.Config global.
+
+It is also possible to create a ConfigState instance that provides methods
+equivalent to the top-level functions.  This allows concurrent configuration
+options.  See the ConfigState documentation for more details.
+
+The following configuration options are available:
+	* Indent
+		String to use for each indentation level for Dump functions.
+		It is a single space by default.  A popular alternative is "\t".
+
+	* MaxDepth
+		Maximum number of levels to descend into nested data structures.
+		There is no limit by default.
+
+	* DisableMethods
+		Disables invocation of error and Stringer interface methods.
+		Method invocation is enabled by default.
+
+	* DisablePointerMethods
+		Disables invocation of error and Stringer interface methods on types
+		which only accept pointer receivers from non-pointer variables.
+		Pointer method invocation is enabled by default.
+
+	* ContinueOnMethod
+		Enables recursion into types after invoking error and Stringer interface
+		methods. Recursion after method invocation is disabled by default.
+
+	* SortKeys
+		Specifies map keys should be sorted before being printed. Use
+		this to have a more deterministic, diffable output.  Note that
+		only native types (bool, int, uint, floats, uintptr and string)
+		and types which implement error or Stringer interfaces are
+		supported with other types sorted according to the
+		reflect.Value.String() output which guarantees display
+		stability.  Natural map order is used by default.
+
+	* SpewKeys
+		Specifies that, as a last resort attempt, map keys should be
+		spewed to strings and sorted by those strings.  This is only
+		considered if SortKeys is true.
+
+Dump Usage
+
+Simply call spew.Dump with a list of variables you want to dump:
+
+	spew.Dump(myVar1, myVar2, ...)
+
+You may also call spew.Fdump if you would prefer to output to an arbitrary
+io.Writer.  For example, to dump to standard error:
+
+	spew.Fdump(os.Stderr, myVar1, myVar2, ...)
+
+A third option is to call spew.Sdump to get the formatted output as a string:
+
+	str := spew.Sdump(myVar1, myVar2, ...)
+
+Sample Dump Output
+
+See the Dump example for details on the setup of the types and variables being
+shown here.
+
+	(main.Foo) {
+	 unexportedField: (*main.Bar)(0xf84002e210)({
+	  flag: (main.Flag) flagTwo,
+	  data: (uintptr) <nil>
+	 }),
+	 ExportedField: (map[interface {}]interface {}) (len=1) {
+	  (string) (len=3) "one": (bool) true
+	 }
+	}
+
+Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
+command as shown.
+	([]uint8) (len=32 cap=32) {
+	 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20  |............... |
+	 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!"#$%&'()*+,-./0|
+	 00000020  31 32                                             |12|
+	}
+
+Custom Formatter
+
+Spew provides a custom formatter that implements the fmt.Formatter interface
+so that it integrates cleanly with standard fmt package printing functions. The
+formatter is useful for inline printing of smaller data types similar to the
+standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
+combinations.  Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting.  In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Custom Formatter Usage
+
+The simplest way to make use of the spew custom formatter is to call one of the
+convenience functions such as spew.Printf, spew.Println, or spew.Printf.  The
+functions have syntax you are most likely already familiar with:
+
+	spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+	spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+	spew.Println(myVar, myVar2)
+	spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
+	spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
+
+See the Index for the full list convenience functions.
+
+Sample Formatter Output
+
+Double pointer to a uint8:
+	  %v: <**>5
+	 %+v: <**>(0xf8400420d0->0xf8400420c8)5
+	 %#v: (**uint8)5
+	%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
+
+Pointer to circular struct with a uint8 field and a pointer to itself:
+	  %v: <*>{1 <*><shown>}
+	 %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
+	 %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
+	%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
+
+See the Printf example for details on the setup of variables being shown
+here.
+
+Errors
+
+Since it is possible for custom Stringer/error interfaces to panic, spew
+detects them and handles them internally by printing the panic information
+inline with the output.  Since spew is intended to provide deep pretty printing
+capabilities on structures, it intentionally does not return any errors.
+*/
+package spew

+ 509 - 0
vendor/github.com/davecgh/go-spew/spew/dump.go

@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"io"
+	"os"
+	"reflect"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+var (
+	// uint8Type is a reflect.Type representing a uint8.  It is used to
+	// convert cgo types to uint8 slices for hexdumping.
+	uint8Type = reflect.TypeOf(uint8(0))
+
+	// cCharRE is a regular expression that matches a cgo char.
+	// It is used to detect character arrays to hexdump them.
+	cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
+
+	// cUnsignedCharRE is a regular expression that matches a cgo unsigned
+	// char.  It is used to detect unsigned character arrays to hexdump
+	// them.
+	cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
+
+	// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
+	// It is used to detect uint8_t arrays to hexdump them.
+	cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
+)
+
+// dumpState contains information about the state of a dump operation.
+type dumpState struct {
+	w                io.Writer
+	depth            int
+	pointers         map[uintptr]int
+	ignoreNextType   bool
+	ignoreNextIndent bool
+	cs               *ConfigState
+}
+
+// indent performs indentation according to the depth level and cs.Indent
+// option.
+func (d *dumpState) indent() {
+	if d.ignoreNextIndent {
+		d.ignoreNextIndent = false
+		return
+	}
+	d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
+}
+
+// unpackValue returns values inside of non-nil interfaces when possible.
+// This is useful for data types like structs, arrays, slices, and maps which
+// can contain varying types packed inside an interface.
+func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
+	if v.Kind() == reflect.Interface && !v.IsNil() {
+		v = v.Elem()
+	}
+	return v
+}
+
+// dumpPtr handles formatting of pointers by indirecting them as necessary.
+func (d *dumpState) dumpPtr(v reflect.Value) {
+	// Remove pointers at or below the current depth from map used to detect
+	// circular refs.
+	for k, depth := range d.pointers {
+		if depth >= d.depth {
+			delete(d.pointers, k)
+		}
+	}
+
+	// Keep list of all dereferenced pointers to show later.
+	pointerChain := make([]uintptr, 0)
+
+	// Figure out how many levels of indirection there are by dereferencing
+	// pointers and unpacking interfaces down the chain while detecting circular
+	// references.
+	nilFound := false
+	cycleFound := false
+	indirects := 0
+	ve := v
+	for ve.Kind() == reflect.Ptr {
+		if ve.IsNil() {
+			nilFound = true
+			break
+		}
+		indirects++
+		addr := ve.Pointer()
+		pointerChain = append(pointerChain, addr)
+		if pd, ok := d.pointers[addr]; ok && pd < d.depth {
+			cycleFound = true
+			indirects--
+			break
+		}
+		d.pointers[addr] = d.depth
+
+		ve = ve.Elem()
+		if ve.Kind() == reflect.Interface {
+			if ve.IsNil() {
+				nilFound = true
+				break
+			}
+			ve = ve.Elem()
+		}
+	}
+
+	// Display type information.
+	d.w.Write(openParenBytes)
+	d.w.Write(bytes.Repeat(asteriskBytes, indirects))
+	d.w.Write([]byte(ve.Type().String()))
+	d.w.Write(closeParenBytes)
+
+	// Display pointer information.
+	if len(pointerChain) > 0 {
+		d.w.Write(openParenBytes)
+		for i, addr := range pointerChain {
+			if i > 0 {
+				d.w.Write(pointerChainBytes)
+			}
+			printHexPtr(d.w, addr)
+		}
+		d.w.Write(closeParenBytes)
+	}
+
+	// Display dereferenced value.
+	d.w.Write(openParenBytes)
+	switch {
+	case nilFound == true:
+		d.w.Write(nilAngleBytes)
+
+	case cycleFound == true:
+		d.w.Write(circularBytes)
+
+	default:
+		d.ignoreNextType = true
+		d.dump(ve)
+	}
+	d.w.Write(closeParenBytes)
+}
+
+// dumpSlice handles formatting of arrays and slices.  Byte (uint8 under
+// reflection) arrays and slices are dumped in hexdump -C fashion.
+func (d *dumpState) dumpSlice(v reflect.Value) {
+	// Determine whether this type should be hex dumped or not.  Also,
+	// for types which should be hexdumped, try to use the underlying data
+	// first, then fall back to trying to convert them to a uint8 slice.
+	var buf []uint8
+	doConvert := false
+	doHexDump := false
+	numEntries := v.Len()
+	if numEntries > 0 {
+		vt := v.Index(0).Type()
+		vts := vt.String()
+		switch {
+		// C types that need to be converted.
+		case cCharRE.MatchString(vts):
+			fallthrough
+		case cUnsignedCharRE.MatchString(vts):
+			fallthrough
+		case cUint8tCharRE.MatchString(vts):
+			doConvert = true
+
+		// Try to use existing uint8 slices and fall back to converting
+		// and copying if that fails.
+		case vt.Kind() == reflect.Uint8:
+			// We need an addressable interface to convert the type
+			// to a byte slice.  However, the reflect package won't
+			// give us an interface on certain things like
+			// unexported struct fields in order to enforce
+			// visibility rules.  We use unsafe, when available, to
+			// bypass these restrictions since this package does not
+			// mutate the values.
+			vs := v
+			if !vs.CanInterface() || !vs.CanAddr() {
+				vs = unsafeReflectValue(vs)
+			}
+			if !UnsafeDisabled {
+				vs = vs.Slice(0, numEntries)
+
+				// Use the existing uint8 slice if it can be
+				// type asserted.
+				iface := vs.Interface()
+				if slice, ok := iface.([]uint8); ok {
+					buf = slice
+					doHexDump = true
+					break
+				}
+			}
+
+			// The underlying data needs to be converted if it can't
+			// be type asserted to a uint8 slice.
+			doConvert = true
+		}
+
+		// Copy and convert the underlying type if needed.
+		if doConvert && vt.ConvertibleTo(uint8Type) {
+			// Convert and copy each element into a uint8 byte
+			// slice.
+			buf = make([]uint8, numEntries)
+			for i := 0; i < numEntries; i++ {
+				vv := v.Index(i)
+				buf[i] = uint8(vv.Convert(uint8Type).Uint())
+			}
+			doHexDump = true
+		}
+	}
+
+	// Hexdump the entire slice as needed.
+	if doHexDump {
+		indent := strings.Repeat(d.cs.Indent, d.depth)
+		str := indent + hex.Dump(buf)
+		str = strings.Replace(str, "\n", "\n"+indent, -1)
+		str = strings.TrimRight(str, d.cs.Indent)
+		d.w.Write([]byte(str))
+		return
+	}
+
+	// Recursively call dump for each item.
+	for i := 0; i < numEntries; i++ {
+		d.dump(d.unpackValue(v.Index(i)))
+		if i < (numEntries - 1) {
+			d.w.Write(commaNewlineBytes)
+		} else {
+			d.w.Write(newlineBytes)
+		}
+	}
+}
+
+// dump is the main workhorse for dumping a value.  It uses the passed reflect
+// value to figure out what kind of object we are dealing with and formats it
+// appropriately.  It is a recursive function, however circular data structures
+// are detected and handled properly.
+func (d *dumpState) dump(v reflect.Value) {
+	// Handle invalid reflect values immediately.
+	kind := v.Kind()
+	if kind == reflect.Invalid {
+		d.w.Write(invalidAngleBytes)
+		return
+	}
+
+	// Handle pointers specially.
+	if kind == reflect.Ptr {
+		d.indent()
+		d.dumpPtr(v)
+		return
+	}
+
+	// Print type information unless already handled elsewhere.
+	if !d.ignoreNextType {
+		d.indent()
+		d.w.Write(openParenBytes)
+		d.w.Write([]byte(v.Type().String()))
+		d.w.Write(closeParenBytes)
+		d.w.Write(spaceBytes)
+	}
+	d.ignoreNextType = false
+
+	// Display length and capacity if the built-in len and cap functions
+	// work with the value's kind and the len/cap itself is non-zero.
+	valueLen, valueCap := 0, 0
+	switch v.Kind() {
+	case reflect.Array, reflect.Slice, reflect.Chan:
+		valueLen, valueCap = v.Len(), v.Cap()
+	case reflect.Map, reflect.String:
+		valueLen = v.Len()
+	}
+	if valueLen != 0 || valueCap != 0 {
+		d.w.Write(openParenBytes)
+		if valueLen != 0 {
+			d.w.Write(lenEqualsBytes)
+			printInt(d.w, int64(valueLen), 10)
+		}
+		if valueCap != 0 {
+			if valueLen != 0 {
+				d.w.Write(spaceBytes)
+			}
+			d.w.Write(capEqualsBytes)
+			printInt(d.w, int64(valueCap), 10)
+		}
+		d.w.Write(closeParenBytes)
+		d.w.Write(spaceBytes)
+	}
+
+	// Call Stringer/error interfaces if they exist and the handle methods flag
+	// is enabled
+	if !d.cs.DisableMethods {
+		if (kind != reflect.Invalid) && (kind != reflect.Interface) {
+			if handled := handleMethods(d.cs, d.w, v); handled {
+				return
+			}
+		}
+	}
+
+	switch kind {
+	case reflect.Invalid:
+		// Do nothing.  We should never get here since invalid has already
+		// been handled above.
+
+	case reflect.Bool:
+		printBool(d.w, v.Bool())
+
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+		printInt(d.w, v.Int(), 10)
+
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+		printUint(d.w, v.Uint(), 10)
+
+	case reflect.Float32:
+		printFloat(d.w, v.Float(), 32)
+
+	case reflect.Float64:
+		printFloat(d.w, v.Float(), 64)
+
+	case reflect.Complex64:
+		printComplex(d.w, v.Complex(), 32)
+
+	case reflect.Complex128:
+		printComplex(d.w, v.Complex(), 64)
+
+	case reflect.Slice:
+		if v.IsNil() {
+			d.w.Write(nilAngleBytes)
+			break
+		}
+		fallthrough
+
+	case reflect.Array:
+		d.w.Write(openBraceNewlineBytes)
+		d.depth++
+		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+			d.indent()
+			d.w.Write(maxNewlineBytes)
+		} else {
+			d.dumpSlice(v)
+		}
+		d.depth--
+		d.indent()
+		d.w.Write(closeBraceBytes)
+
+	case reflect.String:
+		d.w.Write([]byte(strconv.Quote(v.String())))
+
+	case reflect.Interface:
+		// The only time we should get here is for nil interfaces due to
+		// unpackValue calls.
+		if v.IsNil() {
+			d.w.Write(nilAngleBytes)
+		}
+
+	case reflect.Ptr:
+		// Do nothing.  We should never get here since pointers have already
+		// been handled above.
+
+	case reflect.Map:
+		// nil maps should be indicated as different than empty maps
+		if v.IsNil() {
+			d.w.Write(nilAngleBytes)
+			break
+		}
+
+		d.w.Write(openBraceNewlineBytes)
+		d.depth++
+		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+			d.indent()
+			d.w.Write(maxNewlineBytes)
+		} else {
+			numEntries := v.Len()
+			keys := v.MapKeys()
+			if d.cs.SortKeys {
+				sortValues(keys, d.cs)
+			}
+			for i, key := range keys {
+				d.dump(d.unpackValue(key))
+				d.w.Write(colonSpaceBytes)
+				d.ignoreNextIndent = true
+				d.dump(d.unpackValue(v.MapIndex(key)))
+				if i < (numEntries - 1) {
+					d.w.Write(commaNewlineBytes)
+				} else {
+					d.w.Write(newlineBytes)
+				}
+			}
+		}
+		d.depth--
+		d.indent()
+		d.w.Write(closeBraceBytes)
+
+	case reflect.Struct:
+		d.w.Write(openBraceNewlineBytes)
+		d.depth++
+		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
+			d.indent()
+			d.w.Write(maxNewlineBytes)
+		} else {
+			vt := v.Type()
+			numFields := v.NumField()
+			for i := 0; i < numFields; i++ {
+				d.indent()
+				vtf := vt.Field(i)
+				d.w.Write([]byte(vtf.Name))
+				d.w.Write(colonSpaceBytes)
+				d.ignoreNextIndent = true
+				d.dump(d.unpackValue(v.Field(i)))
+				if i < (numFields - 1) {
+					d.w.Write(commaNewlineBytes)
+				} else {
+					d.w.Write(newlineBytes)
+				}
+			}
+		}
+		d.depth--
+		d.indent()
+		d.w.Write(closeBraceBytes)
+
+	case reflect.Uintptr:
+		printHexPtr(d.w, uintptr(v.Uint()))
+
+	case reflect.UnsafePointer, reflect.Chan, reflect.Func:
+		printHexPtr(d.w, v.Pointer())
+
+	// There were not any other types at the time this code was written, but
+	// fall back to letting the default fmt package handle it in case any new
+	// types are added.
+	default:
+		if v.CanInterface() {
+			fmt.Fprintf(d.w, "%v", v.Interface())
+		} else {
+			fmt.Fprintf(d.w, "%v", v.String())
+		}
+	}
+}
+
+// fdump is a helper function to consolidate the logic from the various public
+// methods which take varying writers and config states.
+func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
+	for _, arg := range a {
+		if arg == nil {
+			w.Write(interfaceBytes)
+			w.Write(spaceBytes)
+			w.Write(nilAngleBytes)
+			w.Write(newlineBytes)
+			continue
+		}
+
+		d := dumpState{w: w, cs: cs}
+		d.pointers = make(map[uintptr]int)
+		d.dump(reflect.ValueOf(arg))
+		d.w.Write(newlineBytes)
+	}
+}
+
+// Fdump formats and displays the passed arguments to io.Writer w.  It formats
+// exactly the same as Dump.
+func Fdump(w io.Writer, a ...interface{}) {
+	fdump(&Config, w, a...)
+}
+
+// Sdump returns a string with the passed arguments formatted exactly the same
+// as Dump.
+func Sdump(a ...interface{}) string {
+	var buf bytes.Buffer
+	fdump(&Config, &buf, a...)
+	return buf.String()
+}
+
+/*
+Dump displays the passed parameters to standard out with newlines, customizable
+indentation, and additional debug information such as complete types and all
+pointer addresses used to indirect to the final value.  It provides the
+following features over the built-in printing facilities provided by the fmt
+package:
+
+	* Pointers are dereferenced and followed
+	* Circular data structures are detected and handled properly
+	* Custom Stringer/error interfaces are optionally invoked, including
+	  on unexported types
+	* Custom types which only implement the Stringer/error interfaces via
+	  a pointer receiver are optionally invoked when passing non-pointer
+	  variables
+	* Byte arrays and slices are dumped like the hexdump -C command which
+	  includes offsets, byte values in hex, and ASCII output
+
+The configuration options are controlled by an exported package global,
+spew.Config.  See ConfigState for options documentation.
+
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
+get the formatted result as a string.
+*/
+func Dump(a ...interface{}) {
+	fdump(&Config, os.Stdout, a...)
+}

+ 1042 - 0
vendor/github.com/davecgh/go-spew/spew/dump_test.go

@@ -0,0 +1,1042 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Test Summary:
+NOTE: For each test, a nil pointer, a single pointer and double pointer to the
+base test element are also tested to ensure proper indirection across all types.
+
+- Max int8, int16, int32, int64, int
+- Max uint8, uint16, uint32, uint64, uint
+- Boolean true and false
+- Standard complex64 and complex128
+- Array containing standard ints
+- Array containing type with custom formatter on pointer receiver only
+- Array containing interfaces
+- Array containing bytes
+- Slice containing standard float32 values
+- Slice containing type with custom formatter on pointer receiver only
+- Slice containing interfaces
+- Slice containing bytes
+- Nil slice
+- Standard string
+- Nil interface
+- Sub-interface
+- Map with string keys and int vals
+- Map with custom formatter type on pointer receiver only keys and vals
+- Map with interface keys and values
+- Map with nil interface value
+- Struct with primitives
+- Struct that contains another struct
+- Struct that contains custom type with Stringer pointer interface via both
+  exported and unexported fields
+- Struct that contains embedded struct and field to same struct
+- Uintptr to 0 (null pointer)
+- Uintptr address of real variable
+- Unsafe.Pointer to 0 (null pointer)
+- Unsafe.Pointer to address of real variable
+- Nil channel
+- Standard int channel
+- Function with no params and no returns
+- Function with param and no returns
+- Function with multiple params and multiple returns
+- Struct that is circular through self referencing
+- Structs that are circular through cross referencing
+- Structs that are indirectly circular
+- Type that panics in its Stringer interface
+*/
+
+package spew_test
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+	"unsafe"
+
+	"github.com/davecgh/go-spew/spew"
+)
+
+// dumpTest is used to describe a test to be perfomed against the Dump method.
+type dumpTest struct {
+	in    interface{}
+	wants []string
+}
+
+// dumpTests houses all of the tests to be performed against the Dump method.
+var dumpTests = make([]dumpTest, 0)
+
+// addDumpTest is a helper method to append the passed input and desired result
+// to dumpTests
+func addDumpTest(in interface{}, wants ...string) {
+	test := dumpTest{in, wants}
+	dumpTests = append(dumpTests, test)
+}
+
+func addIntDumpTests() {
+	// Max int8.
+	v := int8(127)
+	nv := (*int8)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "int8"
+	vs := "127"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Max int16.
+	v2 := int16(32767)
+	nv2 := (*int16)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "int16"
+	v2s := "32767"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+
+	// Max int32.
+	v3 := int32(2147483647)
+	nv3 := (*int32)(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "int32"
+	v3s := "2147483647"
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
+	addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
+
+	// Max int64.
+	v4 := int64(9223372036854775807)
+	nv4 := (*int64)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "int64"
+	v4s := "9223372036854775807"
+	addDumpTest(v4, "("+v4t+") "+v4s+"\n")
+	addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
+	addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
+	addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
+
+	// Max int.
+	v5 := int(2147483647)
+	nv5 := (*int)(nil)
+	pv5 := &v5
+	v5Addr := fmt.Sprintf("%p", pv5)
+	pv5Addr := fmt.Sprintf("%p", &pv5)
+	v5t := "int"
+	v5s := "2147483647"
+	addDumpTest(v5, "("+v5t+") "+v5s+"\n")
+	addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n")
+	addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n")
+	addDumpTest(nv5, "(*"+v5t+")(<nil>)\n")
+}
+
+func addUintDumpTests() {
+	// Max uint8.
+	v := uint8(255)
+	nv := (*uint8)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "uint8"
+	vs := "255"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Max uint16.
+	v2 := uint16(65535)
+	nv2 := (*uint16)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "uint16"
+	v2s := "65535"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+
+	// Max uint32.
+	v3 := uint32(4294967295)
+	nv3 := (*uint32)(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "uint32"
+	v3s := "4294967295"
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
+	addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
+
+	// Max uint64.
+	v4 := uint64(18446744073709551615)
+	nv4 := (*uint64)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "uint64"
+	v4s := "18446744073709551615"
+	addDumpTest(v4, "("+v4t+") "+v4s+"\n")
+	addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
+	addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
+	addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
+
+	// Max uint.
+	v5 := uint(4294967295)
+	nv5 := (*uint)(nil)
+	pv5 := &v5
+	v5Addr := fmt.Sprintf("%p", pv5)
+	pv5Addr := fmt.Sprintf("%p", &pv5)
+	v5t := "uint"
+	v5s := "4294967295"
+	addDumpTest(v5, "("+v5t+") "+v5s+"\n")
+	addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n")
+	addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n")
+	addDumpTest(nv5, "(*"+v5t+")(<nil>)\n")
+}
+
+func addBoolDumpTests() {
+	// Boolean true.
+	v := bool(true)
+	nv := (*bool)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "bool"
+	vs := "true"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Boolean false.
+	v2 := bool(false)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "bool"
+	v2s := "false"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+}
+
+func addFloatDumpTests() {
+	// Standard float32.
+	v := float32(3.1415)
+	nv := (*float32)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "float32"
+	vs := "3.1415"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Standard float64.
+	v2 := float64(3.1415926)
+	nv2 := (*float64)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "float64"
+	v2s := "3.1415926"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+}
+
+func addComplexDumpTests() {
+	// Standard complex64.
+	v := complex(float32(6), -2)
+	nv := (*complex64)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "complex64"
+	vs := "(6-2i)"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Standard complex128.
+	v2 := complex(float64(-6), 2)
+	nv2 := (*complex128)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "complex128"
+	v2s := "(-6+2i)"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+}
+
+func addArrayDumpTests() {
+	// Array containing standard ints.
+	v := [3]int{1, 2, 3}
+	vLen := fmt.Sprintf("%d", len(v))
+	vCap := fmt.Sprintf("%d", cap(v))
+	nv := (*[3]int)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "int"
+	vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 1,\n (" +
+		vt + ") 2,\n (" + vt + ") 3\n}"
+	addDumpTest(v, "([3]"+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*[3]"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**[3]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*[3]"+vt+")(<nil>)\n")
+
+	// Array containing type with custom formatter on pointer receiver only.
+	v2i0 := pstringer("1")
+	v2i1 := pstringer("2")
+	v2i2 := pstringer("3")
+	v2 := [3]pstringer{v2i0, v2i1, v2i2}
+	v2i0Len := fmt.Sprintf("%d", len(v2i0))
+	v2i1Len := fmt.Sprintf("%d", len(v2i1))
+	v2i2Len := fmt.Sprintf("%d", len(v2i2))
+	v2Len := fmt.Sprintf("%d", len(v2))
+	v2Cap := fmt.Sprintf("%d", cap(v2))
+	nv2 := (*[3]pstringer)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "spew_test.pstringer"
+	v2sp := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t +
+		") (len=" + v2i0Len + ") stringer 1,\n (" + v2t +
+		") (len=" + v2i1Len + ") stringer 2,\n (" + v2t +
+		") (len=" + v2i2Len + ") " + "stringer 3\n}"
+	v2s := v2sp
+	if spew.UnsafeDisabled {
+		v2s = "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t +
+			") (len=" + v2i0Len + ") \"1\",\n (" + v2t + ") (len=" +
+			v2i1Len + ") \"2\",\n (" + v2t + ") (len=" + v2i2Len +
+			") " + "\"3\"\n}"
+	}
+	addDumpTest(v2, "([3]"+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*[3]"+v2t+")("+v2Addr+")("+v2sp+")\n")
+	addDumpTest(&pv2, "(**[3]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2sp+")\n")
+	addDumpTest(nv2, "(*[3]"+v2t+")(<nil>)\n")
+
+	// Array containing interfaces.
+	v3i0 := "one"
+	v3 := [3]interface{}{v3i0, int(2), uint(3)}
+	v3i0Len := fmt.Sprintf("%d", len(v3i0))
+	v3Len := fmt.Sprintf("%d", len(v3))
+	v3Cap := fmt.Sprintf("%d", cap(v3))
+	nv3 := (*[3]interface{})(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "[3]interface {}"
+	v3t2 := "string"
+	v3t3 := "int"
+	v3t4 := "uint"
+	v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " +
+		"(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" +
+		v3t4 + ") 3\n}"
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
+	addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
+
+	// Array containing bytes.
+	v4 := [34]byte{
+		0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+		0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+		0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+		0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+		0x31, 0x32,
+	}
+	v4Len := fmt.Sprintf("%d", len(v4))
+	v4Cap := fmt.Sprintf("%d", cap(v4))
+	nv4 := (*[34]byte)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "[34]uint8"
+	v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
+		"{\n 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20" +
+		"  |............... |\n" +
+		" 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30" +
+		"  |!\"#$%&'()*+,-./0|\n" +
+		" 00000020  31 32                                           " +
+		"  |12|\n}"
+	addDumpTest(v4, "("+v4t+") "+v4s+"\n")
+	addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
+	addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
+	addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
+}
+
+func addSliceDumpTests() {
+	// Slice containing standard float32 values.
+	v := []float32{3.14, 6.28, 12.56}
+	vLen := fmt.Sprintf("%d", len(v))
+	vCap := fmt.Sprintf("%d", cap(v))
+	nv := (*[]float32)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "float32"
+	vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 3.14,\n (" +
+		vt + ") 6.28,\n (" + vt + ") 12.56\n}"
+	addDumpTest(v, "([]"+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*[]"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**[]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*[]"+vt+")(<nil>)\n")
+
+	// Slice containing type with custom formatter on pointer receiver only.
+	v2i0 := pstringer("1")
+	v2i1 := pstringer("2")
+	v2i2 := pstringer("3")
+	v2 := []pstringer{v2i0, v2i1, v2i2}
+	v2i0Len := fmt.Sprintf("%d", len(v2i0))
+	v2i1Len := fmt.Sprintf("%d", len(v2i1))
+	v2i2Len := fmt.Sprintf("%d", len(v2i2))
+	v2Len := fmt.Sprintf("%d", len(v2))
+	v2Cap := fmt.Sprintf("%d", cap(v2))
+	nv2 := (*[]pstringer)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "spew_test.pstringer"
+	v2s := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" +
+		v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len +
+		") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " +
+		"stringer 3\n}"
+	addDumpTest(v2, "([]"+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*[]"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**[]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*[]"+v2t+")(<nil>)\n")
+
+	// Slice containing interfaces.
+	v3i0 := "one"
+	v3 := []interface{}{v3i0, int(2), uint(3), nil}
+	v3i0Len := fmt.Sprintf("%d", len(v3i0))
+	v3Len := fmt.Sprintf("%d", len(v3))
+	v3Cap := fmt.Sprintf("%d", cap(v3))
+	nv3 := (*[]interface{})(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "[]interface {}"
+	v3t2 := "string"
+	v3t3 := "int"
+	v3t4 := "uint"
+	v3t5 := "interface {}"
+	v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " +
+		"(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" +
+		v3t4 + ") 3,\n (" + v3t5 + ") <nil>\n}"
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
+	addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
+
+	// Slice containing bytes.
+	v4 := []byte{
+		0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+		0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+		0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+		0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+		0x31, 0x32,
+	}
+	v4Len := fmt.Sprintf("%d", len(v4))
+	v4Cap := fmt.Sprintf("%d", cap(v4))
+	nv4 := (*[]byte)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "[]uint8"
+	v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
+		"{\n 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20" +
+		"  |............... |\n" +
+		" 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30" +
+		"  |!\"#$%&'()*+,-./0|\n" +
+		" 00000020  31 32                                           " +
+		"  |12|\n}"
+	addDumpTest(v4, "("+v4t+") "+v4s+"\n")
+	addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
+	addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
+	addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
+
+	// Nil slice.
+	v5 := []int(nil)
+	nv5 := (*[]int)(nil)
+	pv5 := &v5
+	v5Addr := fmt.Sprintf("%p", pv5)
+	pv5Addr := fmt.Sprintf("%p", &pv5)
+	v5t := "[]int"
+	v5s := "<nil>"
+	addDumpTest(v5, "("+v5t+") "+v5s+"\n")
+	addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n")
+	addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n")
+	addDumpTest(nv5, "(*"+v5t+")(<nil>)\n")
+}
+
+func addStringDumpTests() {
+	// Standard string.
+	v := "test"
+	vLen := fmt.Sprintf("%d", len(v))
+	nv := (*string)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "string"
+	vs := "(len=" + vLen + ") \"test\""
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+}
+
+func addInterfaceDumpTests() {
+	// Nil interface.
+	var v interface{}
+	nv := (*interface{})(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "interface {}"
+	vs := "<nil>"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Sub-interface.
+	v2 := interface{}(uint16(65535))
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "uint16"
+	v2s := "65535"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+}
+
+func addMapDumpTests() {
+	// Map with string keys and int vals.
+	k := "one"
+	kk := "two"
+	m := map[string]int{k: 1, kk: 2}
+	klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up
+	kkLen := fmt.Sprintf("%d", len(kk))
+	mLen := fmt.Sprintf("%d", len(m))
+	nilMap := map[string]int(nil)
+	nm := (*map[string]int)(nil)
+	pm := &m
+	mAddr := fmt.Sprintf("%p", pm)
+	pmAddr := fmt.Sprintf("%p", &pm)
+	mt := "map[string]int"
+	mt1 := "string"
+	mt2 := "int"
+	ms := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + klen + ") " +
+		"\"one\": (" + mt2 + ") 1,\n (" + mt1 + ") (len=" + kkLen +
+		") \"two\": (" + mt2 + ") 2\n}"
+	ms2 := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + kkLen + ") " +
+		"\"two\": (" + mt2 + ") 2,\n (" + mt1 + ") (len=" + klen +
+		") \"one\": (" + mt2 + ") 1\n}"
+	addDumpTest(m, "("+mt+") "+ms+"\n", "("+mt+") "+ms2+"\n")
+	addDumpTest(pm, "(*"+mt+")("+mAddr+")("+ms+")\n",
+		"(*"+mt+")("+mAddr+")("+ms2+")\n")
+	addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n",
+		"(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n")
+	addDumpTest(nm, "(*"+mt+")(<nil>)\n")
+	addDumpTest(nilMap, "("+mt+") <nil>\n")
+
+	// Map with custom formatter type on pointer receiver only keys and vals.
+	k2 := pstringer("one")
+	v2 := pstringer("1")
+	m2 := map[pstringer]pstringer{k2: v2}
+	k2Len := fmt.Sprintf("%d", len(k2))
+	v2Len := fmt.Sprintf("%d", len(v2))
+	m2Len := fmt.Sprintf("%d", len(m2))
+	nilMap2 := map[pstringer]pstringer(nil)
+	nm2 := (*map[pstringer]pstringer)(nil)
+	pm2 := &m2
+	m2Addr := fmt.Sprintf("%p", pm2)
+	pm2Addr := fmt.Sprintf("%p", &pm2)
+	m2t := "map[spew_test.pstringer]spew_test.pstringer"
+	m2t1 := "spew_test.pstringer"
+	m2t2 := "spew_test.pstringer"
+	m2s := "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " +
+		"stringer one: (" + m2t2 + ") (len=" + v2Len + ") stringer 1\n}"
+	if spew.UnsafeDisabled {
+		m2s = "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len +
+			") " + "\"one\": (" + m2t2 + ") (len=" + v2Len +
+			") \"1\"\n}"
+	}
+	addDumpTest(m2, "("+m2t+") "+m2s+"\n")
+	addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n")
+	addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n")
+	addDumpTest(nm2, "(*"+m2t+")(<nil>)\n")
+	addDumpTest(nilMap2, "("+m2t+") <nil>\n")
+
+	// Map with interface keys and values.
+	k3 := "one"
+	k3Len := fmt.Sprintf("%d", len(k3))
+	m3 := map[interface{}]interface{}{k3: 1}
+	m3Len := fmt.Sprintf("%d", len(m3))
+	nilMap3 := map[interface{}]interface{}(nil)
+	nm3 := (*map[interface{}]interface{})(nil)
+	pm3 := &m3
+	m3Addr := fmt.Sprintf("%p", pm3)
+	pm3Addr := fmt.Sprintf("%p", &pm3)
+	m3t := "map[interface {}]interface {}"
+	m3t1 := "string"
+	m3t2 := "int"
+	m3s := "(len=" + m3Len + ") {\n (" + m3t1 + ") (len=" + k3Len + ") " +
+		"\"one\": (" + m3t2 + ") 1\n}"
+	addDumpTest(m3, "("+m3t+") "+m3s+"\n")
+	addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n")
+	addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n")
+	addDumpTest(nm3, "(*"+m3t+")(<nil>)\n")
+	addDumpTest(nilMap3, "("+m3t+") <nil>\n")
+
+	// Map with nil interface value.
+	k4 := "nil"
+	k4Len := fmt.Sprintf("%d", len(k4))
+	m4 := map[string]interface{}{k4: nil}
+	m4Len := fmt.Sprintf("%d", len(m4))
+	nilMap4 := map[string]interface{}(nil)
+	nm4 := (*map[string]interface{})(nil)
+	pm4 := &m4
+	m4Addr := fmt.Sprintf("%p", pm4)
+	pm4Addr := fmt.Sprintf("%p", &pm4)
+	m4t := "map[string]interface {}"
+	m4t1 := "string"
+	m4t2 := "interface {}"
+	m4s := "(len=" + m4Len + ") {\n (" + m4t1 + ") (len=" + k4Len + ")" +
+		" \"nil\": (" + m4t2 + ") <nil>\n}"
+	addDumpTest(m4, "("+m4t+") "+m4s+"\n")
+	addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n")
+	addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n")
+	addDumpTest(nm4, "(*"+m4t+")(<nil>)\n")
+	addDumpTest(nilMap4, "("+m4t+") <nil>\n")
+}
+
+func addStructDumpTests() {
+	// Struct with primitives.
+	type s1 struct {
+		a int8
+		b uint8
+	}
+	v := s1{127, 255}
+	nv := (*s1)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.s1"
+	vt2 := "int8"
+	vt3 := "uint8"
+	vs := "{\n a: (" + vt2 + ") 127,\n b: (" + vt3 + ") 255\n}"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Struct that contains another struct.
+	type s2 struct {
+		s1 s1
+		b  bool
+	}
+	v2 := s2{s1{127, 255}, true}
+	nv2 := (*s2)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "spew_test.s2"
+	v2t2 := "spew_test.s1"
+	v2t3 := "int8"
+	v2t4 := "uint8"
+	v2t5 := "bool"
+	v2s := "{\n s1: (" + v2t2 + ") {\n  a: (" + v2t3 + ") 127,\n  b: (" +
+		v2t4 + ") 255\n },\n b: (" + v2t5 + ") true\n}"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+
+	// Struct that contains custom type with Stringer pointer interface via both
+	// exported and unexported fields.
+	type s3 struct {
+		s pstringer
+		S pstringer
+	}
+	v3 := s3{"test", "test2"}
+	nv3 := (*s3)(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "spew_test.s3"
+	v3t2 := "spew_test.pstringer"
+	v3s := "{\n s: (" + v3t2 + ") (len=4) stringer test,\n S: (" + v3t2 +
+		") (len=5) stringer test2\n}"
+	v3sp := v3s
+	if spew.UnsafeDisabled {
+		v3s = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" +
+			v3t2 + ") (len=5) \"test2\"\n}"
+		v3sp = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" +
+			v3t2 + ") (len=5) stringer test2\n}"
+	}
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3sp+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3sp+")\n")
+	addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
+
+	// Struct that contains embedded struct and field to same struct.
+	e := embed{"embedstr"}
+	eLen := fmt.Sprintf("%d", len("embedstr"))
+	v4 := embedwrap{embed: &e, e: &e}
+	nv4 := (*embedwrap)(nil)
+	pv4 := &v4
+	eAddr := fmt.Sprintf("%p", &e)
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "spew_test.embedwrap"
+	v4t2 := "spew_test.embed"
+	v4t3 := "string"
+	v4s := "{\n embed: (*" + v4t2 + ")(" + eAddr + ")({\n  a: (" + v4t3 +
+		") (len=" + eLen + ") \"embedstr\"\n }),\n e: (*" + v4t2 +
+		")(" + eAddr + ")({\n  a: (" + v4t3 + ") (len=" + eLen + ")" +
+		" \"embedstr\"\n })\n}"
+	addDumpTest(v4, "("+v4t+") "+v4s+"\n")
+	addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n")
+	addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n")
+	addDumpTest(nv4, "(*"+v4t+")(<nil>)\n")
+}
+
+func addUintptrDumpTests() {
+	// Null pointer.
+	v := uintptr(0)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "uintptr"
+	vs := "<nil>"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+
+	// Address of real variable.
+	i := 1
+	v2 := uintptr(unsafe.Pointer(&i))
+	nv2 := (*uintptr)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "uintptr"
+	v2s := fmt.Sprintf("%p", &i)
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+}
+
+func addUnsafePointerDumpTests() {
+	// Null pointer.
+	v := unsafe.Pointer(uintptr(0))
+	nv := (*unsafe.Pointer)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "unsafe.Pointer"
+	vs := "<nil>"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Address of real variable.
+	i := 1
+	v2 := unsafe.Pointer(&i)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "unsafe.Pointer"
+	v2s := fmt.Sprintf("%p", &i)
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+}
+
+func addChanDumpTests() {
+	// Nil channel.
+	var v chan int
+	pv := &v
+	nv := (*chan int)(nil)
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "chan int"
+	vs := "<nil>"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Real channel.
+	v2 := make(chan int)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "chan int"
+	v2s := fmt.Sprintf("%p", v2)
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+}
+
+func addFuncDumpTests() {
+	// Function with no params and no returns.
+	v := addIntDumpTests
+	nv := (*func())(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "func()"
+	vs := fmt.Sprintf("%p", v)
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+
+	// Function with param and no returns.
+	v2 := TestDump
+	nv2 := (*func(*testing.T))(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "func(*testing.T)"
+	v2s := fmt.Sprintf("%p", v2)
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n")
+	addDumpTest(nv2, "(*"+v2t+")(<nil>)\n")
+
+	// Function with multiple params and multiple returns.
+	var v3 = func(i int, s string) (b bool, err error) {
+		return true, nil
+	}
+	nv3 := (*func(int, string) (bool, error))(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "func(int, string) (bool, error)"
+	v3s := fmt.Sprintf("%p", v3)
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n")
+	addDumpTest(nv3, "(*"+v3t+")(<nil>)\n")
+}
+
+func addCircularDumpTests() {
+	// Struct that is circular through self referencing.
+	type circular struct {
+		c *circular
+	}
+	v := circular{nil}
+	v.c = &v
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.circular"
+	vs := "{\n c: (*" + vt + ")(" + vAddr + ")({\n  c: (*" + vt + ")(" +
+		vAddr + ")(<already shown>)\n })\n}"
+	vs2 := "{\n c: (*" + vt + ")(" + vAddr + ")(<already shown>)\n}"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs2+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs2+")\n")
+
+	// Structs that are circular through cross referencing.
+	v2 := xref1{nil}
+	ts2 := xref2{&v2}
+	v2.ps2 = &ts2
+	pv2 := &v2
+	ts2Addr := fmt.Sprintf("%p", &ts2)
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "spew_test.xref1"
+	v2t2 := "spew_test.xref2"
+	v2s := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n  ps1: (*" + v2t +
+		")(" + v2Addr + ")({\n   ps2: (*" + v2t2 + ")(" + ts2Addr +
+		")(<already shown>)\n  })\n })\n}"
+	v2s2 := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n  ps1: (*" + v2t +
+		")(" + v2Addr + ")(<already shown>)\n })\n}"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+	addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s2+")\n")
+	addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s2+")\n")
+
+	// Structs that are indirectly circular.
+	v3 := indirCir1{nil}
+	tic2 := indirCir2{nil}
+	tic3 := indirCir3{&v3}
+	tic2.ps3 = &tic3
+	v3.ps2 = &tic2
+	pv3 := &v3
+	tic2Addr := fmt.Sprintf("%p", &tic2)
+	tic3Addr := fmt.Sprintf("%p", &tic3)
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "spew_test.indirCir1"
+	v3t2 := "spew_test.indirCir2"
+	v3t3 := "spew_test.indirCir3"
+	v3s := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n  ps3: (*" + v3t3 +
+		")(" + tic3Addr + ")({\n   ps1: (*" + v3t + ")(" + v3Addr +
+		")({\n    ps2: (*" + v3t2 + ")(" + tic2Addr +
+		")(<already shown>)\n   })\n  })\n })\n}"
+	v3s2 := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n  ps3: (*" + v3t3 +
+		")(" + tic3Addr + ")({\n   ps1: (*" + v3t + ")(" + v3Addr +
+		")(<already shown>)\n  })\n })\n}"
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n")
+	addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s2+")\n")
+	addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s2+")\n")
+}
+
+func addPanicDumpTests() {
+	// Type that panics in its Stringer interface.
+	v := panicer(127)
+	nv := (*panicer)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.panicer"
+	vs := "(PANIC=test panic)127"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+}
+
+func addErrorDumpTests() {
+	// Type that has a custom Error interface.
+	v := customError(127)
+	nv := (*customError)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.customError"
+	vs := "error: 127"
+	addDumpTest(v, "("+vt+") "+vs+"\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n")
+	addDumpTest(nv, "(*"+vt+")(<nil>)\n")
+}
+
+// TestDump executes all of the tests described by dumpTests.
+func TestDump(t *testing.T) {
+	// Setup tests.
+	addIntDumpTests()
+	addUintDumpTests()
+	addBoolDumpTests()
+	addFloatDumpTests()
+	addComplexDumpTests()
+	addArrayDumpTests()
+	addSliceDumpTests()
+	addStringDumpTests()
+	addInterfaceDumpTests()
+	addMapDumpTests()
+	addStructDumpTests()
+	addUintptrDumpTests()
+	addUnsafePointerDumpTests()
+	addChanDumpTests()
+	addFuncDumpTests()
+	addCircularDumpTests()
+	addPanicDumpTests()
+	addErrorDumpTests()
+	addCgoDumpTests()
+
+	t.Logf("Running %d tests", len(dumpTests))
+	for i, test := range dumpTests {
+		buf := new(bytes.Buffer)
+		spew.Fdump(buf, test.in)
+		s := buf.String()
+		if testFailed(s, test.wants) {
+			t.Errorf("Dump #%d\n got: %s %s", i, s, stringizeWants(test.wants))
+			continue
+		}
+	}
+}
+
+func TestDumpSortedKeys(t *testing.T) {
+	cfg := spew.ConfigState{SortKeys: true}
+	s := cfg.Sdump(map[int]string{1: "1", 3: "3", 2: "2"})
+	expected := "(map[int]string) (len=3) {\n(int) 1: (string) (len=1) " +
+		"\"1\",\n(int) 2: (string) (len=1) \"2\",\n(int) 3: (string) " +
+		"(len=1) \"3\"\n" +
+		"}\n"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch:\n  %v %v", s, expected)
+	}
+
+	s = cfg.Sdump(map[stringer]int{"1": 1, "3": 3, "2": 2})
+	expected = "(map[spew_test.stringer]int) (len=3) {\n" +
+		"(spew_test.stringer) (len=1) stringer 1: (int) 1,\n" +
+		"(spew_test.stringer) (len=1) stringer 2: (int) 2,\n" +
+		"(spew_test.stringer) (len=1) stringer 3: (int) 3\n" +
+		"}\n"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch:\n  %v %v", s, expected)
+	}
+
+	s = cfg.Sdump(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2})
+	expected = "(map[spew_test.pstringer]int) (len=3) {\n" +
+		"(spew_test.pstringer) (len=1) stringer 1: (int) 1,\n" +
+		"(spew_test.pstringer) (len=1) stringer 2: (int) 2,\n" +
+		"(spew_test.pstringer) (len=1) stringer 3: (int) 3\n" +
+		"}\n"
+	if spew.UnsafeDisabled {
+		expected = "(map[spew_test.pstringer]int) (len=3) {\n" +
+			"(spew_test.pstringer) (len=1) \"1\": (int) 1,\n" +
+			"(spew_test.pstringer) (len=1) \"2\": (int) 2,\n" +
+			"(spew_test.pstringer) (len=1) \"3\": (int) 3\n" +
+			"}\n"
+	}
+	if s != expected {
+		t.Errorf("Sorted keys mismatch:\n  %v %v", s, expected)
+	}
+
+	s = cfg.Sdump(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2})
+	expected = "(map[spew_test.customError]int) (len=3) {\n" +
+		"(spew_test.customError) error: 1: (int) 1,\n" +
+		"(spew_test.customError) error: 2: (int) 2,\n" +
+		"(spew_test.customError) error: 3: (int) 3\n" +
+		"}\n"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch:\n  %v %v", s, expected)
+	}
+
+}

+ 99 - 0
vendor/github.com/davecgh/go-spew/spew/dumpcgo_test.go

@@ -0,0 +1,99 @@
+// Copyright (c) 2013 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when both cgo is supported and "-tags testcgo" is added to the go test
+// command line.  This means the cgo tests are only added (and hence run) when
+// specifially requested.  This configuration is used because spew itself
+// does not require cgo to run even though it does handle certain cgo types
+// specially.  Rather than forcing all clients to require cgo and an external
+// C compiler just to run the tests, this scheme makes them optional.
+// +build cgo,testcgo
+
+package spew_test
+
+import (
+	"fmt"
+
+	"github.com/davecgh/go-spew/spew/testdata"
+)
+
+func addCgoDumpTests() {
+	// C char pointer.
+	v := testdata.GetCgoCharPointer()
+	nv := testdata.GetCgoNullCharPointer()
+	pv := &v
+	vcAddr := fmt.Sprintf("%p", v)
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "*testdata._Ctype_char"
+	vs := "116"
+	addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n")
+	addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n")
+	addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n")
+	addDumpTest(nv, "("+vt+")(<nil>)\n")
+
+	// C char array.
+	v2, v2l, v2c := testdata.GetCgoCharArray()
+	v2Len := fmt.Sprintf("%d", v2l)
+	v2Cap := fmt.Sprintf("%d", v2c)
+	v2t := "[6]testdata._Ctype_char"
+	v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " +
+		"{\n 00000000  74 65 73 74 32 00                               " +
+		"  |test2.|\n}"
+	addDumpTest(v2, "("+v2t+") "+v2s+"\n")
+
+	// C unsigned char array.
+	v3, v3l, v3c := testdata.GetCgoUnsignedCharArray()
+	v3Len := fmt.Sprintf("%d", v3l)
+	v3Cap := fmt.Sprintf("%d", v3c)
+	v3t := "[6]testdata._Ctype_unsignedchar"
+	v3t2 := "[6]testdata._Ctype_uchar"
+	v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " +
+		"{\n 00000000  74 65 73 74 33 00                               " +
+		"  |test3.|\n}"
+	addDumpTest(v3, "("+v3t+") "+v3s+"\n", "("+v3t2+") "+v3s+"\n")
+
+	// C signed char array.
+	v4, v4l, v4c := testdata.GetCgoSignedCharArray()
+	v4Len := fmt.Sprintf("%d", v4l)
+	v4Cap := fmt.Sprintf("%d", v4c)
+	v4t := "[6]testdata._Ctype_schar"
+	v4t2 := "testdata._Ctype_schar"
+	v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
+		"{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 +
+		") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 +
+		") 0\n}"
+	addDumpTest(v4, "("+v4t+") "+v4s+"\n")
+
+	// C uint8_t array.
+	v5, v5l, v5c := testdata.GetCgoUint8tArray()
+	v5Len := fmt.Sprintf("%d", v5l)
+	v5Cap := fmt.Sprintf("%d", v5c)
+	v5t := "[6]testdata._Ctype_uint8_t"
+	v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " +
+		"{\n 00000000  74 65 73 74 35 00                               " +
+		"  |test5.|\n}"
+	addDumpTest(v5, "("+v5t+") "+v5s+"\n")
+
+	// C typedefed unsigned char array.
+	v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray()
+	v6Len := fmt.Sprintf("%d", v6l)
+	v6Cap := fmt.Sprintf("%d", v6c)
+	v6t := "[6]testdata._Ctype_custom_uchar_t"
+	v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " +
+		"{\n 00000000  74 65 73 74 36 00                               " +
+		"  |test6.|\n}"
+	addDumpTest(v6, "("+v6t+") "+v6s+"\n")
+}

+ 26 - 0
vendor/github.com/davecgh/go-spew/spew/dumpnocgo_test.go

@@ -0,0 +1,26 @@
+// Copyright (c) 2013 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when either cgo is not supported or "-tags testcgo" is not added to the go
+// test command line.  This file intentionally does not setup any cgo tests in
+// this scenario.
+// +build !cgo !testcgo
+
+package spew_test
+
+func addCgoDumpTests() {
+	// Don't add any tests for cgo since this file is only compiled when
+	// there should not be any cgo tests.
+}

+ 226 - 0
vendor/github.com/davecgh/go-spew/spew/example_test.go

@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew_test
+
+import (
+	"fmt"
+
+	"github.com/davecgh/go-spew/spew"
+)
+
+type Flag int
+
+const (
+	flagOne Flag = iota
+	flagTwo
+)
+
+var flagStrings = map[Flag]string{
+	flagOne: "flagOne",
+	flagTwo: "flagTwo",
+}
+
+func (f Flag) String() string {
+	if s, ok := flagStrings[f]; ok {
+		return s
+	}
+	return fmt.Sprintf("Unknown flag (%d)", int(f))
+}
+
+type Bar struct {
+	data uintptr
+}
+
+type Foo struct {
+	unexportedField Bar
+	ExportedField   map[interface{}]interface{}
+}
+
+// This example demonstrates how to use Dump to dump variables to stdout.
+func ExampleDump() {
+	// The following package level declarations are assumed for this example:
+	/*
+		type Flag int
+
+		const (
+			flagOne Flag = iota
+			flagTwo
+		)
+
+		var flagStrings = map[Flag]string{
+			flagOne: "flagOne",
+			flagTwo: "flagTwo",
+		}
+
+		func (f Flag) String() string {
+			if s, ok := flagStrings[f]; ok {
+				return s
+			}
+			return fmt.Sprintf("Unknown flag (%d)", int(f))
+		}
+
+		type Bar struct {
+			data uintptr
+		}
+
+		type Foo struct {
+			unexportedField Bar
+			ExportedField   map[interface{}]interface{}
+		}
+	*/
+
+	// Setup some sample data structures for the example.
+	bar := Bar{uintptr(0)}
+	s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
+	f := Flag(5)
+	b := []byte{
+		0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+		0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+		0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+		0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+		0x31, 0x32,
+	}
+
+	// Dump!
+	spew.Dump(s1, f, b)
+
+	// Output:
+	// (spew_test.Foo) {
+	//  unexportedField: (spew_test.Bar) {
+	//   data: (uintptr) <nil>
+	//  },
+	//  ExportedField: (map[interface {}]interface {}) (len=1) {
+	//   (string) (len=3) "one": (bool) true
+	//  }
+	// }
+	// (spew_test.Flag) Unknown flag (5)
+	// ([]uint8) (len=34 cap=34) {
+	//  00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20  |............... |
+	//  00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!"#$%&'()*+,-./0|
+	//  00000020  31 32                                             |12|
+	// }
+	//
+}
+
+// This example demonstrates how to use Printf to display a variable with a
+// format string and inline formatting.
+func ExamplePrintf() {
+	// Create a double pointer to a uint 8.
+	ui8 := uint8(5)
+	pui8 := &ui8
+	ppui8 := &pui8
+
+	// Create a circular data type.
+	type circular struct {
+		ui8 uint8
+		c   *circular
+	}
+	c := circular{ui8: 1}
+	c.c = &c
+
+	// Print!
+	spew.Printf("ppui8: %v\n", ppui8)
+	spew.Printf("circular: %v\n", c)
+
+	// Output:
+	// ppui8: <**>5
+	// circular: {1 <*>{1 <*><shown>}}
+}
+
+// This example demonstrates how to use a ConfigState.
+func ExampleConfigState() {
+	// Modify the indent level of the ConfigState only.  The global
+	// configuration is not modified.
+	scs := spew.ConfigState{Indent: "\t"}
+
+	// Output using the ConfigState instance.
+	v := map[string]int{"one": 1}
+	scs.Printf("v: %v\n", v)
+	scs.Dump(v)
+
+	// Output:
+	// v: map[one:1]
+	// (map[string]int) (len=1) {
+	// 	(string) (len=3) "one": (int) 1
+	// }
+}
+
+// This example demonstrates how to use ConfigState.Dump to dump variables to
+// stdout
+func ExampleConfigState_Dump() {
+	// See the top-level Dump example for details on the types used in this
+	// example.
+
+	// Create two ConfigState instances with different indentation.
+	scs := spew.ConfigState{Indent: "\t"}
+	scs2 := spew.ConfigState{Indent: " "}
+
+	// Setup some sample data structures for the example.
+	bar := Bar{uintptr(0)}
+	s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
+
+	// Dump using the ConfigState instances.
+	scs.Dump(s1)
+	scs2.Dump(s1)
+
+	// Output:
+	// (spew_test.Foo) {
+	// 	unexportedField: (spew_test.Bar) {
+	// 		data: (uintptr) <nil>
+	// 	},
+	// 	ExportedField: (map[interface {}]interface {}) (len=1) {
+	//		(string) (len=3) "one": (bool) true
+	// 	}
+	// }
+	// (spew_test.Foo) {
+	//  unexportedField: (spew_test.Bar) {
+	//   data: (uintptr) <nil>
+	//  },
+	//  ExportedField: (map[interface {}]interface {}) (len=1) {
+	//   (string) (len=3) "one": (bool) true
+	//  }
+	// }
+	//
+}
+
+// This example demonstrates how to use ConfigState.Printf to display a variable
+// with a format string and inline formatting.
+func ExampleConfigState_Printf() {
+	// See the top-level Dump example for details on the types used in this
+	// example.
+
+	// Create two ConfigState instances and modify the method handling of the
+	// first ConfigState only.
+	scs := spew.NewDefaultConfig()
+	scs2 := spew.NewDefaultConfig()
+	scs.DisableMethods = true
+
+	// Alternatively
+	// scs := spew.ConfigState{Indent: " ", DisableMethods: true}
+	// scs2 := spew.ConfigState{Indent: " "}
+
+	// This is of type Flag which implements a Stringer and has raw value 1.
+	f := flagTwo
+
+	// Dump using the ConfigState instances.
+	scs.Printf("f: %v\n", f)
+	scs2.Printf("f: %v\n", f)
+
+	// Output:
+	// f: 1
+	// f: flagTwo
+}

+ 419 - 0
vendor/github.com/davecgh/go-spew/spew/format.go

@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// supportedFlags is a list of all the character flags supported by fmt package.
+const supportedFlags = "0-+# "
+
+// formatState implements the fmt.Formatter interface and contains information
+// about the state of a formatting operation.  The NewFormatter function can
+// be used to get a new Formatter which can be used directly as arguments
+// in standard fmt package printing calls.
+type formatState struct {
+	value          interface{}
+	fs             fmt.State
+	depth          int
+	pointers       map[uintptr]int
+	ignoreNextType bool
+	cs             *ConfigState
+}
+
+// buildDefaultFormat recreates the original format string without precision
+// and width information to pass in to fmt.Sprintf in the case of an
+// unrecognized type.  Unless new types are added to the language, this
+// function won't ever be called.
+func (f *formatState) buildDefaultFormat() (format string) {
+	buf := bytes.NewBuffer(percentBytes)
+
+	for _, flag := range supportedFlags {
+		if f.fs.Flag(int(flag)) {
+			buf.WriteRune(flag)
+		}
+	}
+
+	buf.WriteRune('v')
+
+	format = buf.String()
+	return format
+}
+
+// constructOrigFormat recreates the original format string including precision
+// and width information to pass along to the standard fmt package.  This allows
+// automatic deferral of all format strings this package doesn't support.
+func (f *formatState) constructOrigFormat(verb rune) (format string) {
+	buf := bytes.NewBuffer(percentBytes)
+
+	for _, flag := range supportedFlags {
+		if f.fs.Flag(int(flag)) {
+			buf.WriteRune(flag)
+		}
+	}
+
+	if width, ok := f.fs.Width(); ok {
+		buf.WriteString(strconv.Itoa(width))
+	}
+
+	if precision, ok := f.fs.Precision(); ok {
+		buf.Write(precisionBytes)
+		buf.WriteString(strconv.Itoa(precision))
+	}
+
+	buf.WriteRune(verb)
+
+	format = buf.String()
+	return format
+}
+
+// unpackValue returns values inside of non-nil interfaces when possible and
+// ensures that types for values which have been unpacked from an interface
+// are displayed when the show types flag is also set.
+// This is useful for data types like structs, arrays, slices, and maps which
+// can contain varying types packed inside an interface.
+func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
+	if v.Kind() == reflect.Interface {
+		f.ignoreNextType = false
+		if !v.IsNil() {
+			v = v.Elem()
+		}
+	}
+	return v
+}
+
+// formatPtr handles formatting of pointers by indirecting them as necessary.
+func (f *formatState) formatPtr(v reflect.Value) {
+	// Display nil if top level pointer is nil.
+	showTypes := f.fs.Flag('#')
+	if v.IsNil() && (!showTypes || f.ignoreNextType) {
+		f.fs.Write(nilAngleBytes)
+		return
+	}
+
+	// Remove pointers at or below the current depth from map used to detect
+	// circular refs.
+	for k, depth := range f.pointers {
+		if depth >= f.depth {
+			delete(f.pointers, k)
+		}
+	}
+
+	// Keep list of all dereferenced pointers to possibly show later.
+	pointerChain := make([]uintptr, 0)
+
+	// Figure out how many levels of indirection there are by derferencing
+	// pointers and unpacking interfaces down the chain while detecting circular
+	// references.
+	nilFound := false
+	cycleFound := false
+	indirects := 0
+	ve := v
+	for ve.Kind() == reflect.Ptr {
+		if ve.IsNil() {
+			nilFound = true
+			break
+		}
+		indirects++
+		addr := ve.Pointer()
+		pointerChain = append(pointerChain, addr)
+		if pd, ok := f.pointers[addr]; ok && pd < f.depth {
+			cycleFound = true
+			indirects--
+			break
+		}
+		f.pointers[addr] = f.depth
+
+		ve = ve.Elem()
+		if ve.Kind() == reflect.Interface {
+			if ve.IsNil() {
+				nilFound = true
+				break
+			}
+			ve = ve.Elem()
+		}
+	}
+
+	// Display type or indirection level depending on flags.
+	if showTypes && !f.ignoreNextType {
+		f.fs.Write(openParenBytes)
+		f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
+		f.fs.Write([]byte(ve.Type().String()))
+		f.fs.Write(closeParenBytes)
+	} else {
+		if nilFound || cycleFound {
+			indirects += strings.Count(ve.Type().String(), "*")
+		}
+		f.fs.Write(openAngleBytes)
+		f.fs.Write([]byte(strings.Repeat("*", indirects)))
+		f.fs.Write(closeAngleBytes)
+	}
+
+	// Display pointer information depending on flags.
+	if f.fs.Flag('+') && (len(pointerChain) > 0) {
+		f.fs.Write(openParenBytes)
+		for i, addr := range pointerChain {
+			if i > 0 {
+				f.fs.Write(pointerChainBytes)
+			}
+			printHexPtr(f.fs, addr)
+		}
+		f.fs.Write(closeParenBytes)
+	}
+
+	// Display dereferenced value.
+	switch {
+	case nilFound == true:
+		f.fs.Write(nilAngleBytes)
+
+	case cycleFound == true:
+		f.fs.Write(circularShortBytes)
+
+	default:
+		f.ignoreNextType = true
+		f.format(ve)
+	}
+}
+
+// format is the main workhorse for providing the Formatter interface.  It
+// uses the passed reflect value to figure out what kind of object we are
+// dealing with and formats it appropriately.  It is a recursive function,
+// however circular data structures are detected and handled properly.
+func (f *formatState) format(v reflect.Value) {
+	// Handle invalid reflect values immediately.
+	kind := v.Kind()
+	if kind == reflect.Invalid {
+		f.fs.Write(invalidAngleBytes)
+		return
+	}
+
+	// Handle pointers specially.
+	if kind == reflect.Ptr {
+		f.formatPtr(v)
+		return
+	}
+
+	// Print type information unless already handled elsewhere.
+	if !f.ignoreNextType && f.fs.Flag('#') {
+		f.fs.Write(openParenBytes)
+		f.fs.Write([]byte(v.Type().String()))
+		f.fs.Write(closeParenBytes)
+	}
+	f.ignoreNextType = false
+
+	// Call Stringer/error interfaces if they exist and the handle methods
+	// flag is enabled.
+	if !f.cs.DisableMethods {
+		if (kind != reflect.Invalid) && (kind != reflect.Interface) {
+			if handled := handleMethods(f.cs, f.fs, v); handled {
+				return
+			}
+		}
+	}
+
+	switch kind {
+	case reflect.Invalid:
+		// Do nothing.  We should never get here since invalid has already
+		// been handled above.
+
+	case reflect.Bool:
+		printBool(f.fs, v.Bool())
+
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+		printInt(f.fs, v.Int(), 10)
+
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+		printUint(f.fs, v.Uint(), 10)
+
+	case reflect.Float32:
+		printFloat(f.fs, v.Float(), 32)
+
+	case reflect.Float64:
+		printFloat(f.fs, v.Float(), 64)
+
+	case reflect.Complex64:
+		printComplex(f.fs, v.Complex(), 32)
+
+	case reflect.Complex128:
+		printComplex(f.fs, v.Complex(), 64)
+
+	case reflect.Slice:
+		if v.IsNil() {
+			f.fs.Write(nilAngleBytes)
+			break
+		}
+		fallthrough
+
+	case reflect.Array:
+		f.fs.Write(openBracketBytes)
+		f.depth++
+		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+			f.fs.Write(maxShortBytes)
+		} else {
+			numEntries := v.Len()
+			for i := 0; i < numEntries; i++ {
+				if i > 0 {
+					f.fs.Write(spaceBytes)
+				}
+				f.ignoreNextType = true
+				f.format(f.unpackValue(v.Index(i)))
+			}
+		}
+		f.depth--
+		f.fs.Write(closeBracketBytes)
+
+	case reflect.String:
+		f.fs.Write([]byte(v.String()))
+
+	case reflect.Interface:
+		// The only time we should get here is for nil interfaces due to
+		// unpackValue calls.
+		if v.IsNil() {
+			f.fs.Write(nilAngleBytes)
+		}
+
+	case reflect.Ptr:
+		// Do nothing.  We should never get here since pointers have already
+		// been handled above.
+
+	case reflect.Map:
+		// nil maps should be indicated as different than empty maps
+		if v.IsNil() {
+			f.fs.Write(nilAngleBytes)
+			break
+		}
+
+		f.fs.Write(openMapBytes)
+		f.depth++
+		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+			f.fs.Write(maxShortBytes)
+		} else {
+			keys := v.MapKeys()
+			if f.cs.SortKeys {
+				sortValues(keys, f.cs)
+			}
+			for i, key := range keys {
+				if i > 0 {
+					f.fs.Write(spaceBytes)
+				}
+				f.ignoreNextType = true
+				f.format(f.unpackValue(key))
+				f.fs.Write(colonBytes)
+				f.ignoreNextType = true
+				f.format(f.unpackValue(v.MapIndex(key)))
+			}
+		}
+		f.depth--
+		f.fs.Write(closeMapBytes)
+
+	case reflect.Struct:
+		numFields := v.NumField()
+		f.fs.Write(openBraceBytes)
+		f.depth++
+		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
+			f.fs.Write(maxShortBytes)
+		} else {
+			vt := v.Type()
+			for i := 0; i < numFields; i++ {
+				if i > 0 {
+					f.fs.Write(spaceBytes)
+				}
+				vtf := vt.Field(i)
+				if f.fs.Flag('+') || f.fs.Flag('#') {
+					f.fs.Write([]byte(vtf.Name))
+					f.fs.Write(colonBytes)
+				}
+				f.format(f.unpackValue(v.Field(i)))
+			}
+		}
+		f.depth--
+		f.fs.Write(closeBraceBytes)
+
+	case reflect.Uintptr:
+		printHexPtr(f.fs, uintptr(v.Uint()))
+
+	case reflect.UnsafePointer, reflect.Chan, reflect.Func:
+		printHexPtr(f.fs, v.Pointer())
+
+	// There were not any other types at the time this code was written, but
+	// fall back to letting the default fmt package handle it if any get added.
+	default:
+		format := f.buildDefaultFormat()
+		if v.CanInterface() {
+			fmt.Fprintf(f.fs, format, v.Interface())
+		} else {
+			fmt.Fprintf(f.fs, format, v.String())
+		}
+	}
+}
+
+// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
+// details.
+func (f *formatState) Format(fs fmt.State, verb rune) {
+	f.fs = fs
+
+	// Use standard formatting for verbs that are not v.
+	if verb != 'v' {
+		format := f.constructOrigFormat(verb)
+		fmt.Fprintf(fs, format, f.value)
+		return
+	}
+
+	if f.value == nil {
+		if fs.Flag('#') {
+			fs.Write(interfaceBytes)
+		}
+		fs.Write(nilAngleBytes)
+		return
+	}
+
+	f.format(reflect.ValueOf(f.value))
+}
+
+// newFormatter is a helper function to consolidate the logic from the various
+// public methods which take varying config states.
+func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
+	fs := &formatState{value: v, cs: cs}
+	fs.pointers = make(map[uintptr]int)
+	return fs
+}
+
+/*
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
+interface.  As a result, it integrates cleanly with standard fmt package
+printing functions.  The formatter is useful for inline printing of smaller data
+types similar to the standard %v format specifier.
+
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
+combinations.  Any other verbs such as %x and %q will be sent to the the
+standard fmt package for formatting.  In addition, the custom formatter ignores
+the width and precision arguments (however they will still work on the format
+specifiers not handled by the custom formatter).
+
+Typically this function shouldn't be called directly.  It is much easier to make
+use of the custom formatter by calling one of the convenience functions such as
+Printf, Println, or Fprintf.
+*/
+func NewFormatter(v interface{}) fmt.Formatter {
+	return newFormatter(&Config, v)
+}

+ 1558 - 0
vendor/github.com/davecgh/go-spew/spew/format_test.go

@@ -0,0 +1,1558 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Test Summary:
+NOTE: For each test, a nil pointer, a single pointer and double pointer to the
+base test element are also tested to ensure proper indirection across all types.
+
+- Max int8, int16, int32, int64, int
+- Max uint8, uint16, uint32, uint64, uint
+- Boolean true and false
+- Standard complex64 and complex128
+- Array containing standard ints
+- Array containing type with custom formatter on pointer receiver only
+- Array containing interfaces
+- Slice containing standard float32 values
+- Slice containing type with custom formatter on pointer receiver only
+- Slice containing interfaces
+- Nil slice
+- Standard string
+- Nil interface
+- Sub-interface
+- Map with string keys and int vals
+- Map with custom formatter type on pointer receiver only keys and vals
+- Map with interface keys and values
+- Map with nil interface value
+- Struct with primitives
+- Struct that contains another struct
+- Struct that contains custom type with Stringer pointer interface via both
+  exported and unexported fields
+- Struct that contains embedded struct and field to same struct
+- Uintptr to 0 (null pointer)
+- Uintptr address of real variable
+- Unsafe.Pointer to 0 (null pointer)
+- Unsafe.Pointer to address of real variable
+- Nil channel
+- Standard int channel
+- Function with no params and no returns
+- Function with param and no returns
+- Function with multiple params and multiple returns
+- Struct that is circular through self referencing
+- Structs that are circular through cross referencing
+- Structs that are indirectly circular
+- Type that panics in its Stringer interface
+- Type that has a custom Error interface
+- %x passthrough with uint
+- %#x passthrough with uint
+- %f passthrough with precision
+- %f passthrough with width and precision
+- %d passthrough with width
+- %q passthrough with string
+*/
+
+package spew_test
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+	"unsafe"
+
+	"github.com/davecgh/go-spew/spew"
+)
+
+// formatterTest is used to describe a test to be perfomed against NewFormatter.
+type formatterTest struct {
+	format string
+	in     interface{}
+	wants  []string
+}
+
+// formatterTests houses all of the tests to be performed against NewFormatter.
+var formatterTests = make([]formatterTest, 0)
+
+// addFormatterTest is a helper method to append the passed input and desired
+// result to formatterTests.
+func addFormatterTest(format string, in interface{}, wants ...string) {
+	test := formatterTest{format, in, wants}
+	formatterTests = append(formatterTests, test)
+}
+
+func addIntFormatterTests() {
+	// Max int8.
+	v := int8(127)
+	nv := (*int8)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "int8"
+	vs := "127"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Max int16.
+	v2 := int16(32767)
+	nv2 := (*int16)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "int16"
+	v2s := "32767"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Max int32.
+	v3 := int32(2147483647)
+	nv3 := (*int32)(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "int32"
+	v3s := "2147483647"
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s)
+	addFormatterTest("%v", &pv3, "<**>"+v3s)
+	addFormatterTest("%v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+
+	// Max int64.
+	v4 := int64(9223372036854775807)
+	nv4 := (*int64)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "int64"
+	v4s := "9223372036854775807"
+	addFormatterTest("%v", v4, v4s)
+	addFormatterTest("%v", pv4, "<*>"+v4s)
+	addFormatterTest("%v", &pv4, "<**>"+v4s)
+	addFormatterTest("%v", nv4, "<nil>")
+	addFormatterTest("%+v", v4, v4s)
+	addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
+	addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%#v", v4, "("+v4t+")"+v4s)
+	addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s)
+	addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s)
+	addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
+	addFormatterTest("%#+v", v4, "("+v4t+")"+v4s)
+	addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s)
+	addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
+
+	// Max int.
+	v5 := int(2147483647)
+	nv5 := (*int)(nil)
+	pv5 := &v5
+	v5Addr := fmt.Sprintf("%p", pv5)
+	pv5Addr := fmt.Sprintf("%p", &pv5)
+	v5t := "int"
+	v5s := "2147483647"
+	addFormatterTest("%v", v5, v5s)
+	addFormatterTest("%v", pv5, "<*>"+v5s)
+	addFormatterTest("%v", &pv5, "<**>"+v5s)
+	addFormatterTest("%v", nv5, "<nil>")
+	addFormatterTest("%+v", v5, v5s)
+	addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s)
+	addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s)
+	addFormatterTest("%+v", nv5, "<nil>")
+	addFormatterTest("%#v", v5, "("+v5t+")"+v5s)
+	addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s)
+	addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s)
+	addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>")
+	addFormatterTest("%#+v", v5, "("+v5t+")"+v5s)
+	addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s)
+	addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s)
+	addFormatterTest("%#+v", nv5, "(*"+v5t+")"+"<nil>")
+}
+
+func addUintFormatterTests() {
+	// Max uint8.
+	v := uint8(255)
+	nv := (*uint8)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "uint8"
+	vs := "255"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Max uint16.
+	v2 := uint16(65535)
+	nv2 := (*uint16)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "uint16"
+	v2s := "65535"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Max uint32.
+	v3 := uint32(4294967295)
+	nv3 := (*uint32)(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "uint32"
+	v3s := "4294967295"
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s)
+	addFormatterTest("%v", &pv3, "<**>"+v3s)
+	addFormatterTest("%v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+
+	// Max uint64.
+	v4 := uint64(18446744073709551615)
+	nv4 := (*uint64)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "uint64"
+	v4s := "18446744073709551615"
+	addFormatterTest("%v", v4, v4s)
+	addFormatterTest("%v", pv4, "<*>"+v4s)
+	addFormatterTest("%v", &pv4, "<**>"+v4s)
+	addFormatterTest("%v", nv4, "<nil>")
+	addFormatterTest("%+v", v4, v4s)
+	addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
+	addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%#v", v4, "("+v4t+")"+v4s)
+	addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s)
+	addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s)
+	addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
+	addFormatterTest("%#+v", v4, "("+v4t+")"+v4s)
+	addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s)
+	addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
+
+	// Max uint.
+	v5 := uint(4294967295)
+	nv5 := (*uint)(nil)
+	pv5 := &v5
+	v5Addr := fmt.Sprintf("%p", pv5)
+	pv5Addr := fmt.Sprintf("%p", &pv5)
+	v5t := "uint"
+	v5s := "4294967295"
+	addFormatterTest("%v", v5, v5s)
+	addFormatterTest("%v", pv5, "<*>"+v5s)
+	addFormatterTest("%v", &pv5, "<**>"+v5s)
+	addFormatterTest("%v", nv5, "<nil>")
+	addFormatterTest("%+v", v5, v5s)
+	addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s)
+	addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s)
+	addFormatterTest("%+v", nv5, "<nil>")
+	addFormatterTest("%#v", v5, "("+v5t+")"+v5s)
+	addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s)
+	addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s)
+	addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>")
+	addFormatterTest("%#+v", v5, "("+v5t+")"+v5s)
+	addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s)
+	addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s)
+	addFormatterTest("%#v", nv5, "(*"+v5t+")"+"<nil>")
+}
+
+func addBoolFormatterTests() {
+	// Boolean true.
+	v := bool(true)
+	nv := (*bool)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "bool"
+	vs := "true"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Boolean false.
+	v2 := bool(false)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "bool"
+	v2s := "false"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+}
+
+func addFloatFormatterTests() {
+	// Standard float32.
+	v := float32(3.1415)
+	nv := (*float32)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "float32"
+	vs := "3.1415"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Standard float64.
+	v2 := float64(3.1415926)
+	nv2 := (*float64)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "float64"
+	v2s := "3.1415926"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+}
+
+func addComplexFormatterTests() {
+	// Standard complex64.
+	v := complex(float32(6), -2)
+	nv := (*complex64)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "complex64"
+	vs := "(6-2i)"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Standard complex128.
+	v2 := complex(float64(-6), 2)
+	nv2 := (*complex128)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "complex128"
+	v2s := "(-6+2i)"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+}
+
+func addArrayFormatterTests() {
+	// Array containing standard ints.
+	v := [3]int{1, 2, 3}
+	nv := (*[3]int)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "[3]int"
+	vs := "[1 2 3]"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Array containing type with custom formatter on pointer receiver only.
+	v2 := [3]pstringer{"1", "2", "3"}
+	nv2 := (*[3]pstringer)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "[3]spew_test.pstringer"
+	v2sp := "[stringer 1 stringer 2 stringer 3]"
+	v2s := v2sp
+	if spew.UnsafeDisabled {
+		v2s = "[1 2 3]"
+	}
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2sp)
+	addFormatterTest("%v", &pv2, "<**>"+v2sp)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2sp)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2sp)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2sp)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2sp)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2sp)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2sp)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Array containing interfaces.
+	v3 := [3]interface{}{"one", int(2), uint(3)}
+	nv3 := (*[3]interface{})(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "[3]interface {}"
+	v3t2 := "string"
+	v3t3 := "int"
+	v3t4 := "uint"
+	v3s := "[one 2 3]"
+	v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3]"
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s)
+	addFormatterTest("%v", &pv3, "<**>"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s2)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2)
+	addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
+}
+
+func addSliceFormatterTests() {
+	// Slice containing standard float32 values.
+	v := []float32{3.14, 6.28, 12.56}
+	nv := (*[]float32)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "[]float32"
+	vs := "[3.14 6.28 12.56]"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Slice containing type with custom formatter on pointer receiver only.
+	v2 := []pstringer{"1", "2", "3"}
+	nv2 := (*[]pstringer)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "[]spew_test.pstringer"
+	v2s := "[stringer 1 stringer 2 stringer 3]"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Slice containing interfaces.
+	v3 := []interface{}{"one", int(2), uint(3), nil}
+	nv3 := (*[]interface{})(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "[]interface {}"
+	v3t2 := "string"
+	v3t3 := "int"
+	v3t4 := "uint"
+	v3t5 := "interface {}"
+	v3s := "[one 2 3 <nil>]"
+	v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3 (" + v3t5 +
+		")<nil>]"
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s)
+	addFormatterTest("%v", &pv3, "<**>"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s2)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2)
+	addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
+
+	// Nil slice.
+	var v4 []int
+	nv4 := (*[]int)(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "[]int"
+	v4s := "<nil>"
+	addFormatterTest("%v", v4, v4s)
+	addFormatterTest("%v", pv4, "<*>"+v4s)
+	addFormatterTest("%v", &pv4, "<**>"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%+v", v4, v4s)
+	addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
+	addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%#v", v4, "("+v4t+")"+v4s)
+	addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s)
+	addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s)
+	addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
+	addFormatterTest("%#+v", v4, "("+v4t+")"+v4s)
+	addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s)
+	addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
+}
+
+func addStringFormatterTests() {
+	// Standard string.
+	v := "test"
+	nv := (*string)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "string"
+	vs := "test"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+}
+
+func addInterfaceFormatterTests() {
+	// Nil interface.
+	var v interface{}
+	nv := (*interface{})(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "interface {}"
+	vs := "<nil>"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Sub-interface.
+	v2 := interface{}(uint16(65535))
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "uint16"
+	v2s := "65535"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+}
+
+func addMapFormatterTests() {
+	// Map with string keys and int vals.
+	v := map[string]int{"one": 1, "two": 2}
+	nilMap := map[string]int(nil)
+	nv := (*map[string]int)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "map[string]int"
+	vs := "map[one:1 two:2]"
+	vs2 := "map[two:2 one:1]"
+	addFormatterTest("%v", v, vs, vs2)
+	addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2)
+	addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2)
+	addFormatterTest("%+v", nilMap, "<nil>")
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs, vs2)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs,
+		"<**>("+pvAddr+"->"+vAddr+")"+vs2)
+	addFormatterTest("%+v", nilMap, "<nil>")
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2)
+	addFormatterTest("%#v", nilMap, "("+vt+")"+"<nil>")
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs,
+		"(*"+vt+")("+vAddr+")"+vs2)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs,
+		"(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2)
+	addFormatterTest("%#+v", nilMap, "("+vt+")"+"<nil>")
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Map with custom formatter type on pointer receiver only keys and vals.
+	v2 := map[pstringer]pstringer{"one": "1"}
+	nv2 := (*map[pstringer]pstringer)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "map[spew_test.pstringer]spew_test.pstringer"
+	v2s := "map[stringer one:stringer 1]"
+	if spew.UnsafeDisabled {
+		v2s = "map[one:1]"
+	}
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Map with interface keys and values.
+	v3 := map[interface{}]interface{}{"one": 1}
+	nv3 := (*map[interface{}]interface{})(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "map[interface {}]interface {}"
+	v3t1 := "string"
+	v3t2 := "int"
+	v3s := "map[one:1]"
+	v3s2 := "map[(" + v3t1 + ")one:(" + v3t2 + ")1]"
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s)
+	addFormatterTest("%v", &pv3, "<**>"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s2)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2)
+	addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
+
+	// Map with nil interface value
+	v4 := map[string]interface{}{"nil": nil}
+	nv4 := (*map[string]interface{})(nil)
+	pv4 := &v4
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "map[string]interface {}"
+	v4t1 := "interface {}"
+	v4s := "map[nil:<nil>]"
+	v4s2 := "map[nil:(" + v4t1 + ")<nil>]"
+	addFormatterTest("%v", v4, v4s)
+	addFormatterTest("%v", pv4, "<*>"+v4s)
+	addFormatterTest("%v", &pv4, "<**>"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%+v", v4, v4s)
+	addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s)
+	addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%#v", v4, "("+v4t+")"+v4s2)
+	addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s2)
+	addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s2)
+	addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
+	addFormatterTest("%#+v", v4, "("+v4t+")"+v4s2)
+	addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s2)
+	addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s2)
+	addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
+}
+
+func addStructFormatterTests() {
+	// Struct with primitives.
+	type s1 struct {
+		a int8
+		b uint8
+	}
+	v := s1{127, 255}
+	nv := (*s1)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.s1"
+	vt2 := "int8"
+	vt3 := "uint8"
+	vs := "{127 255}"
+	vs2 := "{a:127 b:255}"
+	vs3 := "{a:(" + vt2 + ")127 b:(" + vt3 + ")255}"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs2)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs2)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs2)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs3)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs3)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs3)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs3)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs3)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs3)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Struct that contains another struct.
+	type s2 struct {
+		s1 s1
+		b  bool
+	}
+	v2 := s2{s1{127, 255}, true}
+	nv2 := (*s2)(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "spew_test.s2"
+	v2t2 := "spew_test.s1"
+	v2t3 := "int8"
+	v2t4 := "uint8"
+	v2t5 := "bool"
+	v2s := "{{127 255} true}"
+	v2s2 := "{s1:{a:127 b:255} b:true}"
+	v2s3 := "{s1:(" + v2t2 + "){a:(" + v2t3 + ")127 b:(" + v2t4 + ")255} b:(" +
+		v2t5 + ")true}"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s2)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s2)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s2)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s3)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s3)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s3)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s3)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s3)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s3)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Struct that contains custom type with Stringer pointer interface via both
+	// exported and unexported fields.
+	type s3 struct {
+		s pstringer
+		S pstringer
+	}
+	v3 := s3{"test", "test2"}
+	nv3 := (*s3)(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "spew_test.s3"
+	v3t2 := "spew_test.pstringer"
+	v3s := "{stringer test stringer test2}"
+	v3sp := v3s
+	v3s2 := "{s:stringer test S:stringer test2}"
+	v3s2p := v3s2
+	v3s3 := "{s:(" + v3t2 + ")stringer test S:(" + v3t2 + ")stringer test2}"
+	v3s3p := v3s3
+	if spew.UnsafeDisabled {
+		v3s = "{test test2}"
+		v3sp = "{test stringer test2}"
+		v3s2 = "{s:test S:test2}"
+		v3s2p = "{s:test S:stringer test2}"
+		v3s3 = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")test2}"
+		v3s3p = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")stringer test2}"
+	}
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3sp)
+	addFormatterTest("%v", &pv3, "<**>"+v3sp)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s2)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s2p)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s2p)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s3)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s3p)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s3p)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s3)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s3p)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s3p)
+	addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
+
+	// Struct that contains embedded struct and field to same struct.
+	e := embed{"embedstr"}
+	v4 := embedwrap{embed: &e, e: &e}
+	nv4 := (*embedwrap)(nil)
+	pv4 := &v4
+	eAddr := fmt.Sprintf("%p", &e)
+	v4Addr := fmt.Sprintf("%p", pv4)
+	pv4Addr := fmt.Sprintf("%p", &pv4)
+	v4t := "spew_test.embedwrap"
+	v4t2 := "spew_test.embed"
+	v4t3 := "string"
+	v4s := "{<*>{embedstr} <*>{embedstr}}"
+	v4s2 := "{embed:<*>(" + eAddr + "){a:embedstr} e:<*>(" + eAddr +
+		"){a:embedstr}}"
+	v4s3 := "{embed:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 +
+		"){a:(" + v4t3 + ")embedstr}}"
+	v4s4 := "{embed:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 +
+		")embedstr} e:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr}}"
+	addFormatterTest("%v", v4, v4s)
+	addFormatterTest("%v", pv4, "<*>"+v4s)
+	addFormatterTest("%v", &pv4, "<**>"+v4s)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%+v", v4, v4s2)
+	addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s2)
+	addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s2)
+	addFormatterTest("%+v", nv4, "<nil>")
+	addFormatterTest("%#v", v4, "("+v4t+")"+v4s3)
+	addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s3)
+	addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s3)
+	addFormatterTest("%#v", nv4, "(*"+v4t+")"+"<nil>")
+	addFormatterTest("%#+v", v4, "("+v4t+")"+v4s4)
+	addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s4)
+	addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s4)
+	addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"<nil>")
+}
+
+func addUintptrFormatterTests() {
+	// Null pointer.
+	v := uintptr(0)
+	nv := (*uintptr)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "uintptr"
+	vs := "<nil>"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Address of real variable.
+	i := 1
+	v2 := uintptr(unsafe.Pointer(&i))
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "uintptr"
+	v2s := fmt.Sprintf("%p", &i)
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+}
+
+func addUnsafePointerFormatterTests() {
+	// Null pointer.
+	v := unsafe.Pointer(uintptr(0))
+	nv := (*unsafe.Pointer)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "unsafe.Pointer"
+	vs := "<nil>"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Address of real variable.
+	i := 1
+	v2 := unsafe.Pointer(&i)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "unsafe.Pointer"
+	v2s := fmt.Sprintf("%p", &i)
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+}
+
+func addChanFormatterTests() {
+	// Nil channel.
+	var v chan int
+	pv := &v
+	nv := (*chan int)(nil)
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "chan int"
+	vs := "<nil>"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Real channel.
+	v2 := make(chan int)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "chan int"
+	v2s := fmt.Sprintf("%p", v2)
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+}
+
+func addFuncFormatterTests() {
+	// Function with no params and no returns.
+	v := addIntFormatterTests
+	nv := (*func())(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "func()"
+	vs := fmt.Sprintf("%p", v)
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+
+	// Function with param and no returns.
+	v2 := TestFormatter
+	nv2 := (*func(*testing.T))(nil)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "func(*testing.T)"
+	v2s := fmt.Sprintf("%p", v2)
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s)
+	addFormatterTest("%v", &pv2, "<**>"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%+v", v2, v2s)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%+v", nv2, "<nil>")
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s)
+	addFormatterTest("%#v", nv2, "(*"+v2t+")"+"<nil>")
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s)
+	addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"<nil>")
+
+	// Function with multiple params and multiple returns.
+	var v3 = func(i int, s string) (b bool, err error) {
+		return true, nil
+	}
+	nv3 := (*func(int, string) (bool, error))(nil)
+	pv3 := &v3
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "func(int, string) (bool, error)"
+	v3s := fmt.Sprintf("%p", v3)
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s)
+	addFormatterTest("%v", &pv3, "<**>"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%+v", v3, v3s)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%+v", nv3, "<nil>")
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s)
+	addFormatterTest("%#v", nv3, "(*"+v3t+")"+"<nil>")
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s)
+	addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"<nil>")
+}
+
+func addCircularFormatterTests() {
+	// Struct that is circular through self referencing.
+	type circular struct {
+		c *circular
+	}
+	v := circular{nil}
+	v.c = &v
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.circular"
+	vs := "{<*>{<*><shown>}}"
+	vs2 := "{<*><shown>}"
+	vs3 := "{c:<*>(" + vAddr + "){c:<*>(" + vAddr + ")<shown>}}"
+	vs4 := "{c:<*>(" + vAddr + ")<shown>}"
+	vs5 := "{c:(*" + vt + "){c:(*" + vt + ")<shown>}}"
+	vs6 := "{c:(*" + vt + ")<shown>}"
+	vs7 := "{c:(*" + vt + ")(" + vAddr + "){c:(*" + vt + ")(" + vAddr +
+		")<shown>}}"
+	vs8 := "{c:(*" + vt + ")(" + vAddr + ")<shown>}"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs2)
+	addFormatterTest("%v", &pv, "<**>"+vs2)
+	addFormatterTest("%+v", v, vs3)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs4)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs4)
+	addFormatterTest("%#v", v, "("+vt+")"+vs5)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs6)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs6)
+	addFormatterTest("%#+v", v, "("+vt+")"+vs7)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs8)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs8)
+
+	// Structs that are circular through cross referencing.
+	v2 := xref1{nil}
+	ts2 := xref2{&v2}
+	v2.ps2 = &ts2
+	pv2 := &v2
+	ts2Addr := fmt.Sprintf("%p", &ts2)
+	v2Addr := fmt.Sprintf("%p", pv2)
+	pv2Addr := fmt.Sprintf("%p", &pv2)
+	v2t := "spew_test.xref1"
+	v2t2 := "spew_test.xref2"
+	v2s := "{<*>{<*>{<*><shown>}}}"
+	v2s2 := "{<*>{<*><shown>}}"
+	v2s3 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + "){ps2:<*>(" +
+		ts2Addr + ")<shown>}}}"
+	v2s4 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + ")<shown>}}"
+	v2s5 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + "){ps2:(*" + v2t2 +
+		")<shown>}}}"
+	v2s6 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + ")<shown>}}"
+	v2s7 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t +
+		")(" + v2Addr + "){ps2:(*" + v2t2 + ")(" + ts2Addr +
+		")<shown>}}}"
+	v2s8 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t +
+		")(" + v2Addr + ")<shown>}}"
+	addFormatterTest("%v", v2, v2s)
+	addFormatterTest("%v", pv2, "<*>"+v2s2)
+	addFormatterTest("%v", &pv2, "<**>"+v2s2)
+	addFormatterTest("%+v", v2, v2s3)
+	addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s4)
+	addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s4)
+	addFormatterTest("%#v", v2, "("+v2t+")"+v2s5)
+	addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s6)
+	addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s6)
+	addFormatterTest("%#+v", v2, "("+v2t+")"+v2s7)
+	addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s8)
+	addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s8)
+
+	// Structs that are indirectly circular.
+	v3 := indirCir1{nil}
+	tic2 := indirCir2{nil}
+	tic3 := indirCir3{&v3}
+	tic2.ps3 = &tic3
+	v3.ps2 = &tic2
+	pv3 := &v3
+	tic2Addr := fmt.Sprintf("%p", &tic2)
+	tic3Addr := fmt.Sprintf("%p", &tic3)
+	v3Addr := fmt.Sprintf("%p", pv3)
+	pv3Addr := fmt.Sprintf("%p", &pv3)
+	v3t := "spew_test.indirCir1"
+	v3t2 := "spew_test.indirCir2"
+	v3t3 := "spew_test.indirCir3"
+	v3s := "{<*>{<*>{<*>{<*><shown>}}}}"
+	v3s2 := "{<*>{<*>{<*><shown>}}}"
+	v3s3 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" +
+		v3Addr + "){ps2:<*>(" + tic2Addr + ")<shown>}}}}"
+	v3s4 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" +
+		v3Addr + ")<shown>}}}"
+	v3s5 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t +
+		"){ps2:(*" + v3t2 + ")<shown>}}}}"
+	v3s6 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t +
+		")<shown>}}}"
+	v3s7 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" +
+		tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + "){ps2:(*" + v3t2 +
+		")(" + tic2Addr + ")<shown>}}}}"
+	v3s8 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" +
+		tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + ")<shown>}}}"
+	addFormatterTest("%v", v3, v3s)
+	addFormatterTest("%v", pv3, "<*>"+v3s2)
+	addFormatterTest("%v", &pv3, "<**>"+v3s2)
+	addFormatterTest("%+v", v3, v3s3)
+	addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s4)
+	addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s4)
+	addFormatterTest("%#v", v3, "("+v3t+")"+v3s5)
+	addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s6)
+	addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s6)
+	addFormatterTest("%#+v", v3, "("+v3t+")"+v3s7)
+	addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s8)
+	addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s8)
+}
+
+func addPanicFormatterTests() {
+	// Type that panics in its Stringer interface.
+	v := panicer(127)
+	nv := (*panicer)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.panicer"
+	vs := "(PANIC=test panic)127"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+}
+
+func addErrorFormatterTests() {
+	// Type that has a custom Error interface.
+	v := customError(127)
+	nv := (*customError)(nil)
+	pv := &v
+	vAddr := fmt.Sprintf("%p", pv)
+	pvAddr := fmt.Sprintf("%p", &pv)
+	vt := "spew_test.customError"
+	vs := "error: 127"
+	addFormatterTest("%v", v, vs)
+	addFormatterTest("%v", pv, "<*>"+vs)
+	addFormatterTest("%v", &pv, "<**>"+vs)
+	addFormatterTest("%v", nv, "<nil>")
+	addFormatterTest("%+v", v, vs)
+	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs)
+	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%+v", nv, "<nil>")
+	addFormatterTest("%#v", v, "("+vt+")"+vs)
+	addFormatterTest("%#v", pv, "(*"+vt+")"+vs)
+	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs)
+	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
+	addFormatterTest("%#+v", v, "("+vt+")"+vs)
+	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs)
+	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs)
+	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
+}
+
+func addPassthroughFormatterTests() {
+	// %x passthrough with uint.
+	v := uint(4294967295)
+	pv := &v
+	vAddr := fmt.Sprintf("%x", pv)
+	pvAddr := fmt.Sprintf("%x", &pv)
+	vs := "ffffffff"
+	addFormatterTest("%x", v, vs)
+	addFormatterTest("%x", pv, vAddr)
+	addFormatterTest("%x", &pv, pvAddr)
+
+	// %#x passthrough with uint.
+	v2 := int(2147483647)
+	pv2 := &v2
+	v2Addr := fmt.Sprintf("%#x", pv2)
+	pv2Addr := fmt.Sprintf("%#x", &pv2)
+	v2s := "0x7fffffff"
+	addFormatterTest("%#x", v2, v2s)
+	addFormatterTest("%#x", pv2, v2Addr)
+	addFormatterTest("%#x", &pv2, pv2Addr)
+
+	// %f passthrough with precision.
+	addFormatterTest("%.2f", 3.1415, "3.14")
+	addFormatterTest("%.3f", 3.1415, "3.142")
+	addFormatterTest("%.4f", 3.1415, "3.1415")
+
+	// %f passthrough with width and precision.
+	addFormatterTest("%5.2f", 3.1415, " 3.14")
+	addFormatterTest("%6.3f", 3.1415, " 3.142")
+	addFormatterTest("%7.4f", 3.1415, " 3.1415")
+
+	// %d passthrough with width.
+	addFormatterTest("%3d", 127, "127")
+	addFormatterTest("%4d", 127, " 127")
+	addFormatterTest("%5d", 127, "  127")
+
+	// %q passthrough with string.
+	addFormatterTest("%q", "test", "\"test\"")
+}
+
+// TestFormatter executes all of the tests described by formatterTests.
+func TestFormatter(t *testing.T) {
+	// Setup tests.
+	addIntFormatterTests()
+	addUintFormatterTests()
+	addBoolFormatterTests()
+	addFloatFormatterTests()
+	addComplexFormatterTests()
+	addArrayFormatterTests()
+	addSliceFormatterTests()
+	addStringFormatterTests()
+	addInterfaceFormatterTests()
+	addMapFormatterTests()
+	addStructFormatterTests()
+	addUintptrFormatterTests()
+	addUnsafePointerFormatterTests()
+	addChanFormatterTests()
+	addFuncFormatterTests()
+	addCircularFormatterTests()
+	addPanicFormatterTests()
+	addErrorFormatterTests()
+	addPassthroughFormatterTests()
+
+	t.Logf("Running %d tests", len(formatterTests))
+	for i, test := range formatterTests {
+		buf := new(bytes.Buffer)
+		spew.Fprintf(buf, test.format, test.in)
+		s := buf.String()
+		if testFailed(s, test.wants) {
+			t.Errorf("Formatter #%d format: %s got: %s %s", i, test.format, s,
+				stringizeWants(test.wants))
+			continue
+		}
+	}
+}
+
+type testStruct struct {
+	x int
+}
+
+func (ts testStruct) String() string {
+	return fmt.Sprintf("ts.%d", ts.x)
+}
+
+type testStructP struct {
+	x int
+}
+
+func (ts *testStructP) String() string {
+	return fmt.Sprintf("ts.%d", ts.x)
+}
+
+func TestPrintSortedKeys(t *testing.T) {
+	cfg := spew.ConfigState{SortKeys: true}
+	s := cfg.Sprint(map[int]string{1: "1", 3: "3", 2: "2"})
+	expected := "map[1:1 2:2 3:3]"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch 1:\n  %v %v", s, expected)
+	}
+
+	s = cfg.Sprint(map[stringer]int{"1": 1, "3": 3, "2": 2})
+	expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch 2:\n  %v %v", s, expected)
+	}
+
+	s = cfg.Sprint(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2})
+	expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]"
+	if spew.UnsafeDisabled {
+		expected = "map[1:1 2:2 3:3]"
+	}
+	if s != expected {
+		t.Errorf("Sorted keys mismatch 3:\n  %v %v", s, expected)
+	}
+
+	s = cfg.Sprint(map[testStruct]int{testStruct{1}: 1, testStruct{3}: 3, testStruct{2}: 2})
+	expected = "map[ts.1:1 ts.2:2 ts.3:3]"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch 4:\n  %v %v", s, expected)
+	}
+
+	if !spew.UnsafeDisabled {
+		s = cfg.Sprint(map[testStructP]int{testStructP{1}: 1, testStructP{3}: 3, testStructP{2}: 2})
+		expected = "map[ts.1:1 ts.2:2 ts.3:3]"
+		if s != expected {
+			t.Errorf("Sorted keys mismatch 5:\n  %v %v", s, expected)
+		}
+	}
+
+	s = cfg.Sprint(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2})
+	expected = "map[error: 1:1 error: 2:2 error: 3:3]"
+	if s != expected {
+		t.Errorf("Sorted keys mismatch 6:\n  %v %v", s, expected)
+	}
+}

+ 87 - 0
vendor/github.com/davecgh/go-spew/spew/internal_test.go

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+This test file is part of the spew package rather than than the spew_test
+package because it needs access to internals to properly test certain cases
+which are not possible via the public interface since they should never happen.
+*/
+
+package spew
+
+import (
+	"bytes"
+	"reflect"
+	"testing"
+)
+
+// dummyFmtState implements a fake fmt.State to use for testing invalid
+// reflect.Value handling.  This is necessary because the fmt package catches
+// invalid values before invoking the formatter on them.
+type dummyFmtState struct {
+	bytes.Buffer
+}
+
+func (dfs *dummyFmtState) Flag(f int) bool {
+	if f == int('+') {
+		return true
+	}
+	return false
+}
+
+func (dfs *dummyFmtState) Precision() (int, bool) {
+	return 0, false
+}
+
+func (dfs *dummyFmtState) Width() (int, bool) {
+	return 0, false
+}
+
+// TestInvalidReflectValue ensures the dump and formatter code handles an
+// invalid reflect value properly.  This needs access to internal state since it
+// should never happen in real code and therefore can't be tested via the public
+// API.
+func TestInvalidReflectValue(t *testing.T) {
+	i := 1
+
+	// Dump invalid reflect value.
+	v := new(reflect.Value)
+	buf := new(bytes.Buffer)
+	d := dumpState{w: buf, cs: &Config}
+	d.dump(*v)
+	s := buf.String()
+	want := "<invalid>"
+	if s != want {
+		t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want)
+	}
+	i++
+
+	// Formatter invalid reflect value.
+	buf2 := new(dummyFmtState)
+	f := formatState{value: *v, cs: &Config, fs: buf2}
+	f.format(*v)
+	s = buf2.String()
+	want = "<invalid>"
+	if s != want {
+		t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want)
+	}
+}
+
+// SortValues makes the internal sortValues function available to the test
+// package.
+func SortValues(values []reflect.Value, cs *ConfigState) {
+	sortValues(values, cs)
+}

+ 102 - 0
vendor/github.com/davecgh/go-spew/spew/internalunsafe_test.go

@@ -0,0 +1,102 @@
+// Copyright (c) 2013-2015 Dave Collins <dave@davec.name>
+
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when the code is not running on Google App Engine, compiled by GopherJS, and
+// "-tags safe" is not added to the go build command line.  The "disableunsafe"
+// tag is deprecated and thus should not be used.
+// +build !js,!appengine,!safe,!disableunsafe
+
+/*
+This test file is part of the spew package rather than than the spew_test
+package because it needs access to internals to properly test certain cases
+which are not possible via the public interface since they should never happen.
+*/
+
+package spew
+
+import (
+	"bytes"
+	"reflect"
+	"testing"
+	"unsafe"
+)
+
+// changeKind uses unsafe to intentionally change the kind of a reflect.Value to
+// the maximum kind value which does not exist.  This is needed to test the
+// fallback code which punts to the standard fmt library for new types that
+// might get added to the language.
+func changeKind(v *reflect.Value, readOnly bool) {
+	rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag))
+	*rvf = *rvf | ((1<<flagKindWidth - 1) << flagKindShift)
+	if readOnly {
+		*rvf |= flagRO
+	} else {
+		*rvf &= ^uintptr(flagRO)
+	}
+}
+
+// TestAddedReflectValue tests functionaly of the dump and formatter code which
+// falls back to the standard fmt library for new types that might get added to
+// the language.
+func TestAddedReflectValue(t *testing.T) {
+	i := 1
+
+	// Dump using a reflect.Value that is exported.
+	v := reflect.ValueOf(int8(5))
+	changeKind(&v, false)
+	buf := new(bytes.Buffer)
+	d := dumpState{w: buf, cs: &Config}
+	d.dump(v)
+	s := buf.String()
+	want := "(int8) 5"
+	if s != want {
+		t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
+	}
+	i++
+
+	// Dump using a reflect.Value that is not exported.
+	changeKind(&v, true)
+	buf.Reset()
+	d.dump(v)
+	s = buf.String()
+	want = "(int8) <int8 Value>"
+	if s != want {
+		t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
+	}
+	i++
+
+	// Formatter using a reflect.Value that is exported.
+	changeKind(&v, false)
+	buf2 := new(dummyFmtState)
+	f := formatState{value: v, cs: &Config, fs: buf2}
+	f.format(v)
+	s = buf2.String()
+	want = "5"
+	if s != want {
+		t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
+	}
+	i++
+
+	// Formatter using a reflect.Value that is not exported.
+	changeKind(&v, true)
+	buf2.Reset()
+	f = formatState{value: v, cs: &Config, fs: buf2}
+	f.format(v)
+	s = buf2.String()
+	want = "<int8 Value>"
+	if s != want {
+		t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
+	}
+}

+ 148 - 0
vendor/github.com/davecgh/go-spew/spew/spew.go

@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew
+
+import (
+	"fmt"
+	"io"
+)
+
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the formatted string as a value that satisfies error.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Errorf(format string, a ...interface{}) (err error) {
+	return fmt.Errorf(format, convertArgs(a)...)
+}
+
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+	return fmt.Fprint(w, convertArgs(a)...)
+}
+
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+	return fmt.Fprintf(w, format, convertArgs(a)...)
+}
+
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
+// passed with a default Formatter interface returned by NewFormatter.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
+func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+	return fmt.Fprintln(w, convertArgs(a)...)
+}
+
+// Print is a wrapper for fmt.Print that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
+func Print(a ...interface{}) (n int, err error) {
+	return fmt.Print(convertArgs(a)...)
+}
+
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Printf(format string, a ...interface{}) (n int, err error) {
+	return fmt.Printf(format, convertArgs(a)...)
+}
+
+// Println is a wrapper for fmt.Println that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the number of bytes written and any write error encountered.  See
+// NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
+func Println(a ...interface{}) (n int, err error) {
+	return fmt.Println(convertArgs(a)...)
+}
+
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the resulting string.  See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprint(a ...interface{}) string {
+	return fmt.Sprint(convertArgs(a)...)
+}
+
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
+// passed with a default Formatter interface returned by NewFormatter.  It
+// returns the resulting string.  See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprintf(format string, a ...interface{}) string {
+	return fmt.Sprintf(format, convertArgs(a)...)
+}
+
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
+// were passed with a default Formatter interface returned by NewFormatter.  It
+// returns the resulting string.  See NewFormatter for formatting details.
+//
+// This function is shorthand for the following syntax:
+//
+//	fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
+func Sprintln(a ...interface{}) string {
+	return fmt.Sprintln(convertArgs(a)...)
+}
+
+// convertArgs accepts a slice of arguments and returns a slice of the same
+// length with each argument converted to a default spew Formatter interface.
+func convertArgs(args []interface{}) (formatters []interface{}) {
+	formatters = make([]interface{}, len(args))
+	for index, arg := range args {
+		formatters[index] = NewFormatter(arg)
+	}
+	return formatters
+}

+ 309 - 0
vendor/github.com/davecgh/go-spew/spew/spew_test.go

@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package spew_test
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"testing"
+
+	"github.com/davecgh/go-spew/spew"
+)
+
+// spewFunc is used to identify which public function of the spew package or
+// ConfigState a test applies to.
+type spewFunc int
+
+const (
+	fCSFdump spewFunc = iota
+	fCSFprint
+	fCSFprintf
+	fCSFprintln
+	fCSPrint
+	fCSPrintln
+	fCSSdump
+	fCSSprint
+	fCSSprintf
+	fCSSprintln
+	fCSErrorf
+	fCSNewFormatter
+	fErrorf
+	fFprint
+	fFprintln
+	fPrint
+	fPrintln
+	fSdump
+	fSprint
+	fSprintf
+	fSprintln
+)
+
+// Map of spewFunc values to names for pretty printing.
+var spewFuncStrings = map[spewFunc]string{
+	fCSFdump:        "ConfigState.Fdump",
+	fCSFprint:       "ConfigState.Fprint",
+	fCSFprintf:      "ConfigState.Fprintf",
+	fCSFprintln:     "ConfigState.Fprintln",
+	fCSSdump:        "ConfigState.Sdump",
+	fCSPrint:        "ConfigState.Print",
+	fCSPrintln:      "ConfigState.Println",
+	fCSSprint:       "ConfigState.Sprint",
+	fCSSprintf:      "ConfigState.Sprintf",
+	fCSSprintln:     "ConfigState.Sprintln",
+	fCSErrorf:       "ConfigState.Errorf",
+	fCSNewFormatter: "ConfigState.NewFormatter",
+	fErrorf:         "spew.Errorf",
+	fFprint:         "spew.Fprint",
+	fFprintln:       "spew.Fprintln",
+	fPrint:          "spew.Print",
+	fPrintln:        "spew.Println",
+	fSdump:          "spew.Sdump",
+	fSprint:         "spew.Sprint",
+	fSprintf:        "spew.Sprintf",
+	fSprintln:       "spew.Sprintln",
+}
+
+func (f spewFunc) String() string {
+	if s, ok := spewFuncStrings[f]; ok {
+		return s
+	}
+	return fmt.Sprintf("Unknown spewFunc (%d)", int(f))
+}
+
+// spewTest is used to describe a test to be performed against the public
+// functions of the spew package or ConfigState.
+type spewTest struct {
+	cs     *spew.ConfigState
+	f      spewFunc
+	format string
+	in     interface{}
+	want   string
+}
+
+// spewTests houses the tests to be performed against the public functions of
+// the spew package and ConfigState.
+//
+// These tests are only intended to ensure the public functions are exercised
+// and are intentionally not exhaustive of types.  The exhaustive type
+// tests are handled in the dump and format tests.
+var spewTests []spewTest
+
+// redirStdout is a helper function to return the standard output from f as a
+// byte slice.
+func redirStdout(f func()) ([]byte, error) {
+	tempFile, err := ioutil.TempFile("", "ss-test")
+	if err != nil {
+		return nil, err
+	}
+	fileName := tempFile.Name()
+	defer os.Remove(fileName) // Ignore error
+
+	origStdout := os.Stdout
+	os.Stdout = tempFile
+	f()
+	os.Stdout = origStdout
+	tempFile.Close()
+
+	return ioutil.ReadFile(fileName)
+}
+
+func initSpewTests() {
+	// Config states with various settings.
+	scsDefault := spew.NewDefaultConfig()
+	scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true}
+	scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
+	scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
+	scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
+
+	// Variables for tests on types which implement Stringer interface with and
+	// without a pointer receiver.
+	ts := stringer("test")
+	tps := pstringer("test")
+
+	// depthTester is used to test max depth handling for structs, array, slices
+	// and maps.
+	type depthTester struct {
+		ic    indirCir1
+		arr   [1]string
+		slice []string
+		m     map[string]int
+	}
+	dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"},
+		map[string]int{"one": 1}}
+
+	// Variable for tests on types which implement error interface.
+	te := customError(10)
+
+	spewTests = []spewTest{
+		{scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"},
+		{scsDefault, fCSFprint, "", int16(32767), "32767"},
+		{scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"},
+		{scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"},
+		{scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"},
+		{scsDefault, fCSPrintln, "", uint8(255), "255\n"},
+		{scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"},
+		{scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"},
+		{scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"},
+		{scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"},
+		{scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"},
+		{scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"},
+		{scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"},
+		{scsDefault, fFprint, "", float32(3.14), "3.14"},
+		{scsDefault, fFprintln, "", float64(6.28), "6.28\n"},
+		{scsDefault, fPrint, "", true, "true"},
+		{scsDefault, fPrintln, "", false, "false\n"},
+		{scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"},
+		{scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"},
+		{scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"},
+		{scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"},
+		{scsNoMethods, fCSFprint, "", ts, "test"},
+		{scsNoMethods, fCSFprint, "", &ts, "<*>test"},
+		{scsNoMethods, fCSFprint, "", tps, "test"},
+		{scsNoMethods, fCSFprint, "", &tps, "<*>test"},
+		{scsNoPmethods, fCSFprint, "", ts, "stringer test"},
+		{scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"},
+		{scsNoPmethods, fCSFprint, "", tps, "test"},
+		{scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"},
+		{scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"},
+		{scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" +
+			" ic: (spew_test.indirCir1) {\n  <max depth reached>\n },\n" +
+			" arr: ([1]string) (len=1 cap=1) {\n  <max depth reached>\n },\n" +
+			" slice: ([]string) (len=1 cap=1) {\n  <max depth reached>\n },\n" +
+			" m: (map[string]int) (len=1) {\n  <max depth reached>\n }\n}\n"},
+		{scsContinue, fCSFprint, "", ts, "(stringer test) test"},
+		{scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " +
+			"(len=4) (stringer test) \"test\"\n"},
+		{scsContinue, fCSFprint, "", te, "(error: 10) 10"},
+		{scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
+			"(error: 10) 10\n"},
+	}
+}
+
+// TestSpew executes all of the tests described by spewTests.
+func TestSpew(t *testing.T) {
+	initSpewTests()
+
+	t.Logf("Running %d tests", len(spewTests))
+	for i, test := range spewTests {
+		buf := new(bytes.Buffer)
+		switch test.f {
+		case fCSFdump:
+			test.cs.Fdump(buf, test.in)
+
+		case fCSFprint:
+			test.cs.Fprint(buf, test.in)
+
+		case fCSFprintf:
+			test.cs.Fprintf(buf, test.format, test.in)
+
+		case fCSFprintln:
+			test.cs.Fprintln(buf, test.in)
+
+		case fCSPrint:
+			b, err := redirStdout(func() { test.cs.Print(test.in) })
+			if err != nil {
+				t.Errorf("%v #%d %v", test.f, i, err)
+				continue
+			}
+			buf.Write(b)
+
+		case fCSPrintln:
+			b, err := redirStdout(func() { test.cs.Println(test.in) })
+			if err != nil {
+				t.Errorf("%v #%d %v", test.f, i, err)
+				continue
+			}
+			buf.Write(b)
+
+		case fCSSdump:
+			str := test.cs.Sdump(test.in)
+			buf.WriteString(str)
+
+		case fCSSprint:
+			str := test.cs.Sprint(test.in)
+			buf.WriteString(str)
+
+		case fCSSprintf:
+			str := test.cs.Sprintf(test.format, test.in)
+			buf.WriteString(str)
+
+		case fCSSprintln:
+			str := test.cs.Sprintln(test.in)
+			buf.WriteString(str)
+
+		case fCSErrorf:
+			err := test.cs.Errorf(test.format, test.in)
+			buf.WriteString(err.Error())
+
+		case fCSNewFormatter:
+			fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in))
+
+		case fErrorf:
+			err := spew.Errorf(test.format, test.in)
+			buf.WriteString(err.Error())
+
+		case fFprint:
+			spew.Fprint(buf, test.in)
+
+		case fFprintln:
+			spew.Fprintln(buf, test.in)
+
+		case fPrint:
+			b, err := redirStdout(func() { spew.Print(test.in) })
+			if err != nil {
+				t.Errorf("%v #%d %v", test.f, i, err)
+				continue
+			}
+			buf.Write(b)
+
+		case fPrintln:
+			b, err := redirStdout(func() { spew.Println(test.in) })
+			if err != nil {
+				t.Errorf("%v #%d %v", test.f, i, err)
+				continue
+			}
+			buf.Write(b)
+
+		case fSdump:
+			str := spew.Sdump(test.in)
+			buf.WriteString(str)
+
+		case fSprint:
+			str := spew.Sprint(test.in)
+			buf.WriteString(str)
+
+		case fSprintf:
+			str := spew.Sprintf(test.format, test.in)
+			buf.WriteString(str)
+
+		case fSprintln:
+			str := spew.Sprintln(test.in)
+			buf.WriteString(str)
+
+		default:
+			t.Errorf("%v #%d unrecognized function", test.f, i)
+			continue
+		}
+		s := buf.String()
+		if test.want != s {
+			t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
+			continue
+		}
+	}
+}

+ 82 - 0
vendor/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go

@@ -0,0 +1,82 @@
+// Copyright (c) 2013 Dave Collins <dave@davec.name>
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// NOTE: Due to the following build constraints, this file will only be compiled
+// when both cgo is supported and "-tags testcgo" is added to the go test
+// command line.  This code should really only be in the dumpcgo_test.go file,
+// but unfortunately Go will not allow cgo in test files, so this is a
+// workaround to allow cgo types to be tested.  This configuration is used
+// because spew itself does not require cgo to run even though it does handle
+// certain cgo types specially.  Rather than forcing all clients to require cgo
+// and an external C compiler just to run the tests, this scheme makes them
+// optional.
+// +build cgo,testcgo
+
+package testdata
+
+/*
+#include <stdint.h>
+typedef unsigned char custom_uchar_t;
+
+char            *ncp = 0;
+char            *cp = "test";
+char             ca[6] = {'t', 'e', 's', 't', '2', '\0'};
+unsigned char    uca[6] = {'t', 'e', 's', 't', '3', '\0'};
+signed char      sca[6] = {'t', 'e', 's', 't', '4', '\0'};
+uint8_t          ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'};
+custom_uchar_t   tuca[6] = {'t', 'e', 's', 't', '6', '\0'};
+*/
+import "C"
+
+// GetCgoNullCharPointer returns a null char pointer via cgo.  This is only
+// used for tests.
+func GetCgoNullCharPointer() interface{} {
+	return C.ncp
+}
+
+// GetCgoCharPointer returns a char pointer via cgo.  This is only used for
+// tests.
+func GetCgoCharPointer() interface{} {
+	return C.cp
+}
+
+// GetCgoCharArray returns a char array via cgo and the array's len and cap.
+// This is only used for tests.
+func GetCgoCharArray() (interface{}, int, int) {
+	return C.ca, len(C.ca), cap(C.ca)
+}
+
+// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the
+// array's len and cap.  This is only used for tests.
+func GetCgoUnsignedCharArray() (interface{}, int, int) {
+	return C.uca, len(C.uca), cap(C.uca)
+}
+
+// GetCgoSignedCharArray returns a signed char array via cgo and the array's len
+// and cap.  This is only used for tests.
+func GetCgoSignedCharArray() (interface{}, int, int) {
+	return C.sca, len(C.sca), cap(C.sca)
+}
+
+// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and
+// cap.  This is only used for tests.
+func GetCgoUint8tArray() (interface{}, int, int) {
+	return C.ui8ta, len(C.ui8ta), cap(C.ui8ta)
+}
+
+// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via
+// cgo and the array's len and cap.  This is only used for tests.
+func GetCgoTypdefedUnsignedCharArray() (interface{}, int, int) {
+	return C.tuca, len(C.tuca), cap(C.tuca)
+}

+ 61 - 0
vendor/github.com/davecgh/go-spew/test_coverage.txt

@@ -0,0 +1,61 @@
+
+github.com/davecgh/go-spew/spew/dump.go		 dumpState.dump			 100.00% (88/88)
+github.com/davecgh/go-spew/spew/format.go	 formatState.format		 100.00% (82/82)
+github.com/davecgh/go-spew/spew/format.go	 formatState.formatPtr		 100.00% (52/52)
+github.com/davecgh/go-spew/spew/dump.go		 dumpState.dumpPtr		 100.00% (44/44)
+github.com/davecgh/go-spew/spew/dump.go		 dumpState.dumpSlice		 100.00% (39/39)
+github.com/davecgh/go-spew/spew/common.go	 handleMethods			 100.00% (30/30)
+github.com/davecgh/go-spew/spew/common.go	 printHexPtr			 100.00% (18/18)
+github.com/davecgh/go-spew/spew/common.go	 unsafeReflectValue		 100.00% (13/13)
+github.com/davecgh/go-spew/spew/format.go	 formatState.constructOrigFormat 100.00% (12/12)
+github.com/davecgh/go-spew/spew/dump.go		 fdump				 100.00% (11/11)
+github.com/davecgh/go-spew/spew/format.go	 formatState.Format		 100.00% (11/11)
+github.com/davecgh/go-spew/spew/common.go	 init				 100.00% (10/10)
+github.com/davecgh/go-spew/spew/common.go	 printComplex			 100.00% (9/9)
+github.com/davecgh/go-spew/spew/common.go	 valuesSorter.Less		 100.00% (8/8)
+github.com/davecgh/go-spew/spew/format.go	 formatState.buildDefaultFormat	 100.00% (7/7)
+github.com/davecgh/go-spew/spew/format.go	 formatState.unpackValue	 100.00% (5/5)
+github.com/davecgh/go-spew/spew/dump.go		 dumpState.indent		 100.00% (4/4)
+github.com/davecgh/go-spew/spew/common.go	 catchPanic			 100.00% (4/4)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.convertArgs	 100.00% (4/4)
+github.com/davecgh/go-spew/spew/spew.go		 convertArgs			 100.00% (4/4)
+github.com/davecgh/go-spew/spew/format.go	 newFormatter			 100.00% (3/3)
+github.com/davecgh/go-spew/spew/dump.go		 Sdump				 100.00% (3/3)
+github.com/davecgh/go-spew/spew/common.go	 printBool			 100.00% (3/3)
+github.com/davecgh/go-spew/spew/common.go	 sortValues			 100.00% (3/3)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Sdump		 100.00% (3/3)
+github.com/davecgh/go-spew/spew/dump.go		 dumpState.unpackValue		 100.00% (3/3)
+github.com/davecgh/go-spew/spew/spew.go		 Printf				 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Println			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Sprint				 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Sprintf			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Sprintln			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/common.go	 printFloat			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 NewDefaultConfig		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/common.go	 printInt			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/common.go	 printUint			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/common.go	 valuesSorter.Len		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/common.go	 valuesSorter.Swap		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Errorf		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Fprint		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Fprintf		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Fprintln		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Print		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Printf		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Println		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Sprint		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Sprintf		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Sprintln		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.NewFormatter	 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Fdump		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/config.go	 ConfigState.Dump		 100.00% (1/1)
+github.com/davecgh/go-spew/spew/dump.go		 Fdump				 100.00% (1/1)
+github.com/davecgh/go-spew/spew/dump.go		 Dump				 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Fprintln			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/format.go	 NewFormatter			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Errorf				 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Fprint				 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Fprintf			 100.00% (1/1)
+github.com/davecgh/go-spew/spew/spew.go		 Print				 100.00% (1/1)
+github.com/davecgh/go-spew/spew			 ------------------------------- 100.00% (505/505)
+

+ 96 - 0
vendor/github.com/jmespath/go-jmespath/compliance/basic.json

@@ -0,0 +1,96 @@
+[{
+    "given":
+        {"foo": {"bar": {"baz": "correct"}}},
+     "cases": [
+         {
+            "expression": "foo",
+            "result": {"bar": {"baz": "correct"}}
+         },
+         {
+            "expression": "foo.bar",
+            "result": {"baz": "correct"}
+         },
+         {
+            "expression": "foo.bar.baz",
+            "result": "correct"
+         },
+         {
+            "expression": "foo\n.\nbar\n.baz",
+            "result": "correct"
+         },
+         {
+            "expression": "foo.bar.baz.bad",
+            "result": null
+         },
+         {
+            "expression": "foo.bar.bad",
+            "result": null
+         },
+         {
+            "expression": "foo.bad",
+            "result": null
+         },
+         {
+            "expression": "bad",
+            "result": null
+         },
+         {
+            "expression": "bad.morebad.morebad",
+            "result": null
+         }
+     ]
+},
+{
+    "given":
+        {"foo": {"bar": ["one", "two", "three"]}},
+    "cases": [
+         {
+            "expression": "foo",
+            "result": {"bar": ["one", "two", "three"]}
+         },
+         {
+            "expression": "foo.bar",
+            "result": ["one", "two", "three"]
+         }
+    ]
+},
+{
+    "given": ["one", "two", "three"],
+    "cases": [
+        {
+            "expression": "one",
+            "result": null
+        },
+        {
+            "expression": "two",
+            "result": null
+        },
+        {
+            "expression": "three",
+            "result": null
+        },
+        {
+            "expression": "one.two",
+            "result": null
+        }
+    ]
+},
+{
+    "given":
+        {"foo": {"1": ["one", "two", "three"], "-1": "bar"}},
+    "cases": [
+         {
+            "expression": "foo.\"1\"",
+            "result": ["one", "two", "three"]
+         },
+         {
+            "expression": "foo.\"1\"[0]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.\"-1\"",
+            "result": "bar"
+         }
+    ]
+}
+]

+ 257 - 0
vendor/github.com/jmespath/go-jmespath/compliance/boolean.json

@@ -0,0 +1,257 @@
+[
+  {
+    "given": {
+      "outer": {
+        "foo": "foo",
+        "bar": "bar",
+        "baz": "baz"
+      }
+    },
+    "cases": [
+      {
+        "expression": "outer.foo || outer.bar",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.foo||outer.bar",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.bar || outer.baz",
+        "result": "bar"
+      },
+      {
+        "expression": "outer.bar||outer.baz",
+        "result": "bar"
+      },
+      {
+        "expression": "outer.bad || outer.foo",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.bad||outer.foo",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.foo || outer.bad",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.foo||outer.bad",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.bad || outer.alsobad",
+        "result": null
+      },
+      {
+        "expression": "outer.bad||outer.alsobad",
+        "result": null
+      }
+    ]
+  },
+  {
+    "given": {
+      "outer": {
+        "foo": "foo",
+        "bool": false,
+        "empty_list": [],
+        "empty_string": ""
+      }
+    },
+    "cases": [
+      {
+        "expression": "outer.empty_string || outer.foo",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo",
+        "result": "foo"
+      }
+    ]
+  },
+  {
+    "given": {
+      "True": true,
+      "False": false,
+      "Number": 5,
+      "EmptyList": [],
+      "Zero": 0
+    },
+    "cases": [
+      {
+        "expression": "True && False",
+        "result": false
+      },
+      {
+        "expression": "False && True",
+        "result": false
+      },
+      {
+        "expression": "True && True",
+        "result": true
+      },
+      {
+        "expression": "False && False",
+        "result": false
+      },
+      {
+        "expression": "True && Number",
+        "result": 5
+      },
+      {
+        "expression": "Number && True",
+        "result": true
+      },
+      {
+        "expression": "Number && False",
+        "result": false
+      },
+      {
+        "expression": "Number && EmptyList",
+        "result": []
+      },
+      {
+        "expression": "Number && True",
+        "result": true
+      },
+      {
+        "expression": "EmptyList && True",
+        "result": []
+      },
+      {
+        "expression": "EmptyList && False",
+        "result": []
+      },
+      {
+        "expression": "True || False",
+        "result": true
+      },
+      {
+        "expression": "True || True",
+        "result": true
+      },
+      {
+        "expression": "False || True",
+        "result": true
+      },
+      {
+        "expression": "False || False",
+        "result": false
+      },
+      {
+        "expression": "Number || EmptyList",
+        "result": 5
+      },
+      {
+        "expression": "Number || True",
+        "result": 5
+      },
+      {
+        "expression": "Number || True && False",
+        "result": 5
+      },
+      {
+        "expression": "(Number || True) && False",
+        "result": false
+      },
+      {
+        "expression": "Number || (True && False)",
+        "result": 5
+      },
+      {
+        "expression": "!True",
+        "result": false
+      },
+      {
+        "expression": "!False",
+        "result": true
+      },
+      {
+        "expression": "!Number",
+        "result": false
+      },
+      {
+        "expression": "!EmptyList",
+        "result": true
+      },
+      {
+        "expression": "True && !False",
+        "result": true
+      },
+      {
+        "expression": "True && !EmptyList",
+        "result": true
+      },
+      {
+        "expression": "!False && !EmptyList",
+        "result": true
+      },
+      {
+        "expression": "!(True && False)",
+        "result": true
+      },
+      {
+        "expression": "!Zero",
+        "result": false
+      },
+      {
+        "expression": "!!Zero",
+        "result": true
+      }
+    ]
+  },
+  {
+    "given": {
+      "one": 1,
+      "two": 2,
+      "three": 3
+    },
+    "cases": [
+      {
+        "expression": "one < two",
+        "result": true
+      },
+      {
+        "expression": "one <= two",
+        "result": true
+      },
+      {
+        "expression": "one == one",
+        "result": true
+      },
+      {
+        "expression": "one == two",
+        "result": false
+      },
+      {
+        "expression": "one > two",
+        "result": false
+      },
+      {
+        "expression": "one >= two",
+        "result": false
+      },
+      {
+        "expression": "one != two",
+        "result": true
+      },
+      {
+        "expression": "one < two && three > one",
+        "result": true
+      },
+      {
+        "expression": "one < two || three > one",
+        "result": true
+      },
+      {
+        "expression": "one < two || three < one",
+        "result": true
+      },
+      {
+        "expression": "two < one || three < one",
+        "result": false
+      }
+    ]
+  }
+]

+ 25 - 0
vendor/github.com/jmespath/go-jmespath/compliance/current.json

@@ -0,0 +1,25 @@
+[
+    {
+        "given": {
+            "foo": [{"name": "a"}, {"name": "b"}],
+            "bar": {"baz": "qux"}
+        },
+        "cases": [
+            {
+                "expression": "@",
+                "result": {
+                    "foo": [{"name": "a"}, {"name": "b"}],
+                    "bar": {"baz": "qux"}
+                }
+            },
+            {
+                "expression": "@.bar",
+                "result": {"baz": "qux"}
+            },
+            {
+                "expression": "@.foo[0]",
+                "result": {"name": "a"}
+            }
+        ]
+    }
+]

+ 46 - 0
vendor/github.com/jmespath/go-jmespath/compliance/escape.json

@@ -0,0 +1,46 @@
+[{
+    "given": {
+        "foo.bar": "dot",
+        "foo bar": "space",
+        "foo\nbar": "newline",
+        "foo\"bar": "doublequote",
+        "c:\\\\windows\\path": "windows",
+        "/unix/path": "unix",
+        "\"\"\"": "threequotes",
+        "bar": {"baz": "qux"}
+     },
+     "cases": [
+         {
+            "expression": "\"foo.bar\"",
+            "result": "dot"
+         },
+         {
+            "expression": "\"foo bar\"",
+            "result": "space"
+         },
+         {
+            "expression": "\"foo\\nbar\"",
+            "result": "newline"
+         },
+         {
+            "expression": "\"foo\\\"bar\"",
+            "result": "doublequote"
+         },
+         {
+            "expression": "\"c:\\\\\\\\windows\\\\path\"",
+            "result": "windows"
+         },
+         {
+            "expression": "\"/unix/path\"",
+            "result": "unix"
+         },
+         {
+            "expression": "\"\\\"\\\"\\\"\"",
+            "result": "threequotes"
+         },
+         {
+            "expression": "\"bar\".\"baz\"",
+            "result": "qux"
+         }
+     ]
+}]

+ 468 - 0
vendor/github.com/jmespath/go-jmespath/compliance/filters.json

@@ -0,0 +1,468 @@
+[
+  {
+    "given": {"foo": [{"name": "a"}, {"name": "b"}]},
+    "cases": [
+      {
+        "comment": "Matching a literal",
+        "expression": "foo[?name == 'a']",
+        "result": [{"name": "a"}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [0, 1], "bar": [2, 3]},
+    "cases": [
+      {
+        "comment": "Matching a literal",
+        "expression": "*[?[0] == `0`]",
+        "result": [[], []]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"first": "foo", "last": "bar"},
+      {"first": "foo", "last": "foo"},
+      {"first": "foo", "last": "baz"}]},
+    "cases": [
+      {
+        "comment": "Matching an expression",
+        "expression": "foo[?first == last]",
+        "result": [{"first": "foo", "last": "foo"}]
+      },
+      {
+        "comment": "Verify projection created from filter",
+        "expression": "foo[?first == last].first",
+        "result": ["foo"]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"age": 20},
+      {"age": 25},
+      {"age": 30}]},
+    "cases": [
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age > `25`]",
+        "result": [{"age": 30}]
+      },
+      {
+        "expression": "foo[?age >= `25`]",
+        "result": [{"age": 25}, {"age": 30}]
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age > `30`]",
+        "result": []
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age < `25`]",
+        "result": [{"age": 20}]
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age <= `25`]",
+        "result": [{"age": 20}, {"age": 25}]
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age < `20`]",
+        "result": []
+      },
+      {
+        "expression": "foo[?age == `20`]",
+        "result": [{"age": 20}]
+      },
+      {
+        "expression": "foo[?age != `20`]",
+        "result": [{"age": 25}, {"age": 30}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"top": {"name": "a"}},
+      {"top": {"name": "b"}}]},
+    "cases": [
+      {
+        "comment": "Filter with subexpression",
+        "expression": "foo[?top.name == 'a']",
+        "result": [{"top": {"name": "a"}}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"top": {"first": "foo", "last": "bar"}},
+      {"top": {"first": "foo", "last": "foo"}},
+      {"top": {"first": "foo", "last": "baz"}}]},
+    "cases": [
+      {
+        "comment": "Matching an expression",
+        "expression": "foo[?top.first == top.last]",
+        "result": [{"top": {"first": "foo", "last": "foo"}}]
+      },
+      {
+        "comment": "Matching a JSON array",
+        "expression": "foo[?top == `{\"first\": \"foo\", \"last\": \"bar\"}`]",
+        "result": [{"top": {"first": "foo", "last": "bar"}}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [
+      {"key": true},
+      {"key": false},
+      {"key": 0},
+      {"key": 1},
+      {"key": [0]},
+      {"key": {"bar": [0]}},
+      {"key": null},
+      {"key": [1]},
+      {"key": {"a":2}}
+    ]},
+    "cases": [
+      {
+        "expression": "foo[?key == `true`]",
+        "result": [{"key": true}]
+      },
+      {
+        "expression": "foo[?key == `false`]",
+        "result": [{"key": false}]
+      },
+      {
+        "expression": "foo[?key == `0`]",
+        "result": [{"key": 0}]
+      },
+      {
+        "expression": "foo[?key == `1`]",
+        "result": [{"key": 1}]
+      },
+      {
+        "expression": "foo[?key == `[0]`]",
+        "result": [{"key": [0]}]
+      },
+      {
+        "expression": "foo[?key == `{\"bar\": [0]}`]",
+        "result": [{"key": {"bar": [0]}}]
+      },
+      {
+        "expression": "foo[?key == `null`]",
+        "result": [{"key": null}]
+      },
+      {
+        "expression": "foo[?key == `[1]`]",
+        "result": [{"key": [1]}]
+      },
+      {
+        "expression": "foo[?key == `{\"a\":2}`]",
+        "result": [{"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`true` == key]",
+        "result": [{"key": true}]
+      },
+      {
+        "expression": "foo[?`false` == key]",
+        "result": [{"key": false}]
+      },
+      {
+        "expression": "foo[?`0` == key]",
+        "result": [{"key": 0}]
+      },
+      {
+        "expression": "foo[?`1` == key]",
+        "result": [{"key": 1}]
+      },
+      {
+        "expression": "foo[?`[0]` == key]",
+        "result": [{"key": [0]}]
+      },
+      {
+        "expression": "foo[?`{\"bar\": [0]}` == key]",
+        "result": [{"key": {"bar": [0]}}]
+      },
+      {
+        "expression": "foo[?`null` == key]",
+        "result": [{"key": null}]
+      },
+      {
+        "expression": "foo[?`[1]` == key]",
+        "result": [{"key": [1]}]
+      },
+      {
+        "expression": "foo[?`{\"a\":2}` == key]",
+        "result": [{"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `true`]",
+        "result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `false`]",
+        "result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `0`]",
+        "result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `1`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `null`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `[1]`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `{\"a\":2}`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
+      },
+      {
+        "expression": "foo[?`true` != key]",
+        "result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`false` != key]",
+        "result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`0` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`1` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`null` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`[1]` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`{\"a\":2}` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
+      }
+    ]
+  },
+  {
+    "given": {"reservations": [
+      {"instances": [
+        {"foo": 1, "bar": 2}, {"foo": 1, "bar": 3},
+        {"foo": 1, "bar": 2}, {"foo": 2, "bar": 1}]}]},
+    "cases": [
+      {
+        "expression": "reservations[].instances[?bar==`1`]",
+        "result": [[{"foo": 2, "bar": 1}]]
+      },
+      {
+        "expression": "reservations[*].instances[?bar==`1`]",
+        "result": [[{"foo": 2, "bar": 1}]]
+      },
+      {
+        "expression": "reservations[].instances[?bar==`1`][]",
+        "result": [{"foo": 2, "bar": 1}]
+      }
+    ]
+  },
+  {
+    "given": {
+      "baz": "other",
+      "foo": [
+        {"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 1, "baz": 2}
+      ]
+    },
+    "cases": [
+      {
+        "expression": "foo[?bar==`1`].bar[0]",
+        "result": []
+      }
+    ]
+  },
+  {
+    "given": {
+      "foo": [
+        {"a": 1, "b": {"c": "x"}},
+	{"a": 1, "b": {"c": "y"}},
+	{"a": 1, "b": {"c": "z"}},
+	{"a": 2, "b": {"c": "z"}},
+	{"a": 1, "baz": 2}
+      ]
+    },
+    "cases": [
+      {
+        "expression": "foo[?a==`1`].b.c",
+        "result": ["x", "y", "z"]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"name": "a"}, {"name": "b"}, {"name": "c"}]},
+    "cases": [
+      {
+        "comment": "Filter with or expression",
+        "expression": "foo[?name == 'a' || name == 'b']",
+        "result": [{"name": "a"}, {"name": "b"}]
+      },
+      {
+        "expression": "foo[?name == 'a' || name == 'e']",
+        "result": [{"name": "a"}]
+      },
+      {
+        "expression": "foo[?name == 'a' || name == 'b' || name == 'c']",
+        "result": [{"name": "a"}, {"name": "b"}, {"name": "c"}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]},
+    "cases": [
+      {
+        "comment": "Filter with and expression",
+        "expression": "foo[?a == `1` && b == `2`]",
+        "result": [{"a": 1, "b": 2}]
+      },
+      {
+        "expression": "foo[?a == `1` && b == `4`]",
+        "result": []
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
+    "cases": [
+      {
+        "comment": "Filter with Or and And expressions",
+        "expression": "foo[?c == `3` || a == `1` && b == `4`]",
+        "result": [{"a": 1, "b": 2, "c": 3}]
+      },
+      {
+        "expression": "foo[?b == `2` || a == `3` && b == `4`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?a == `3` && b == `4` || b == `2`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?(a == `3` && b == `4`) || b == `2`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?((a == `3` && b == `4`)) || b == `2`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?a == `3` && (b == `4` || b == `2`)]",
+        "result": [{"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?a == `3` && ((b == `4` || b == `2`))]",
+        "result": [{"a": 3, "b": 4}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
+    "cases": [
+      {
+        "comment": "Verify precedence of or/and expressions",
+        "expression": "foo[?a == `1` || b ==`2` && c == `5`]",
+        "result": [{"a": 1, "b": 2, "c": 3}]
+      },
+      {
+        "comment": "Parentheses can alter precedence",
+        "expression": "foo[?(a == `1` || b ==`2`) && c == `5`]",
+        "result": []
+      },
+      {
+        "comment": "Not expressions combined with and/or",
+        "expression": "foo[?!(a == `1` || b ==`2`)]",
+        "result": [{"a": 3, "b": 4}]
+      }
+    ]
+  },
+  {
+    "given": {
+      "foo": [
+        {"key": true},
+        {"key": false},
+        {"key": []},
+        {"key": {}},
+        {"key": [0]},
+        {"key": {"a": "b"}},
+        {"key": 0},
+        {"key": 1},
+        {"key": null},
+        {"notkey": true}
+      ]
+    },
+    "cases": [
+      {
+        "comment": "Unary filter expression",
+        "expression": "foo[?key]",
+        "result": [
+          {"key": true}, {"key": [0]}, {"key": {"a": "b"}},
+          {"key": 0}, {"key": 1}
+        ]
+      },
+      {
+        "comment": "Unary not filter expression",
+        "expression": "foo[?!key]",
+        "result": [
+          {"key": false}, {"key": []}, {"key": {}},
+          {"key": null}, {"notkey": true}
+        ]
+      },
+      {
+        "comment": "Equality with null RHS",
+        "expression": "foo[?key == `null`]",
+        "result": [
+          {"key": null}, {"notkey": true}
+        ]
+      }
+    ]
+  },
+  {
+    "given": {
+      "foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    "cases": [
+      {
+        "comment": "Using @ in a filter expression",
+        "expression": "foo[?@ < `5`]",
+        "result": [0, 1, 2, 3, 4]
+      },
+      {
+        "comment": "Using @ in a filter expression",
+        "expression": "foo[?`5` > @]",
+        "result": [0, 1, 2, 3, 4]
+      },
+      {
+        "comment": "Using @ in a filter expression",
+        "expression": "foo[?@ == @]",
+        "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+      }
+    ]
+  }
+]

+ 825 - 0
vendor/github.com/jmespath/go-jmespath/compliance/functions.json

@@ -0,0 +1,825 @@
+[{
+  "given":
+  {
+    "foo": -1,
+    "zero": 0,
+    "numbers": [-1, 3, 4, 5],
+    "array": [-1, 3, 4, 5, "a", "100"],
+    "strings": ["a", "b", "c"],
+    "decimals": [1.01, 1.2, -1.5],
+    "str": "Str",
+    "false": false,
+    "empty_list": [],
+    "empty_hash": {},
+    "objects": {"foo": "bar", "bar": "baz"},
+    "null_key": null
+  },
+  "cases": [
+    {
+      "expression": "abs(foo)",
+      "result": 1
+    },
+    {
+      "expression": "abs(foo)",
+      "result": 1
+    },
+    {
+      "expression": "abs(str)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "abs(array[1])",
+      "result": 3
+    },
+    {
+      "expression": "abs(array[1])",
+      "result": 3
+    },
+    {
+      "expression": "abs(`false`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "abs(`-24`)",
+      "result": 24
+    },
+    {
+      "expression": "abs(`-24`)",
+      "result": 24
+    },
+    {
+      "expression": "abs(`1`, `2`)",
+      "error": "invalid-arity"
+    },
+    {
+      "expression": "abs()",
+      "error": "invalid-arity"
+    },
+    {
+      "expression": "unknown_function(`1`, `2`)",
+      "error": "unknown-function"
+    },
+    {
+      "expression": "avg(numbers)",
+      "result": 2.75
+    },
+    {
+      "expression": "avg(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg('abc')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg(@)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg(strings)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "ceil(`1.2`)",
+      "result": 2
+    },
+    {
+      "expression": "ceil(decimals[0])",
+      "result": 2
+    },
+    {
+      "expression": "ceil(decimals[1])",
+      "result": 2
+    },
+    {
+      "expression": "ceil(decimals[2])",
+      "result": -1
+    },
+    {
+      "expression": "ceil('string')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "contains('abc', 'a')",
+      "result": true
+    },
+    {
+      "expression": "contains('abc', 'd')",
+      "result": false
+    },
+    {
+      "expression": "contains(`false`, 'd')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "contains(strings, 'a')",
+      "result": true
+    },
+    {
+      "expression": "contains(decimals, `1.2`)",
+      "result": true
+    },
+    {
+      "expression": "contains(decimals, `false`)",
+      "result": false
+    },
+    {
+      "expression": "ends_with(str, 'r')",
+      "result": true
+    },
+    {
+      "expression": "ends_with(str, 'tr')",
+      "result": true
+    },
+    {
+      "expression": "ends_with(str, 'Str')",
+      "result": true
+    },
+    {
+      "expression": "ends_with(str, 'SStr')",
+      "result": false
+    },
+    {
+      "expression": "ends_with(str, 'foo')",
+      "result": false
+    },
+    {
+      "expression": "ends_with(str, `0`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "floor(`1.2`)",
+      "result": 1
+    },
+    {
+      "expression": "floor('string')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "floor(decimals[0])",
+      "result": 1
+    },
+    {
+      "expression": "floor(foo)",
+      "result": -1
+    },
+    {
+      "expression": "floor(str)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "length('abc')",
+      "result": 3
+    },
+    {
+      "expression": "length('✓foo')",
+      "result": 4
+    },
+    {
+      "expression": "length('')",
+      "result": 0
+    },
+    {
+      "expression": "length(@)",
+      "result": 12
+    },
+    {
+      "expression": "length(strings[0])",
+      "result": 1
+    },
+    {
+      "expression": "length(str)",
+      "result": 3
+    },
+    {
+      "expression": "length(array)",
+      "result": 6
+    },
+    {
+      "expression": "length(objects)",
+      "result": 2
+    },
+    {
+      "expression": "length(`false`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "length(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "length(strings[0])",
+      "result": 1
+    },
+    {
+      "expression": "max(numbers)",
+      "result": 5
+    },
+    {
+      "expression": "max(decimals)",
+      "result": 1.2
+    },
+    {
+      "expression": "max(strings)",
+      "result": "c"
+    },
+    {
+      "expression": "max(abc)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max(decimals)",
+      "result": 1.2
+    },
+    {
+      "expression": "max(empty_list)",
+      "result": null
+    },
+    {
+      "expression": "merge(`{}`)",
+      "result": {}
+    },
+    {
+      "expression": "merge(`{}`, `{}`)",
+      "result": {}
+    },
+    {
+      "expression": "merge(`{\"a\": 1}`, `{\"b\": 2}`)",
+      "result": {"a": 1, "b": 2}
+    },
+    {
+      "expression": "merge(`{\"a\": 1}`, `{\"a\": 2}`)",
+      "result": {"a": 2}
+    },
+    {
+      "expression": "merge(`{\"a\": 1, \"b\": 2}`, `{\"a\": 2, \"c\": 3}`, `{\"d\": 4}`)",
+      "result": {"a": 2, "b": 2, "c": 3, "d": 4}
+    },
+    {
+      "expression": "min(numbers)",
+      "result": -1
+    },
+    {
+      "expression": "min(decimals)",
+      "result": -1.5
+    },
+    {
+      "expression": "min(abc)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min(empty_list)",
+      "result": null
+    },
+    {
+      "expression": "min(decimals)",
+      "result": -1.5
+    },
+    {
+      "expression": "min(strings)",
+      "result": "a"
+    },
+    {
+      "expression": "type('abc')",
+      "result": "string"
+    },
+    {
+      "expression": "type(`1.0`)",
+      "result": "number"
+    },
+    {
+      "expression": "type(`2`)",
+      "result": "number"
+    },
+    {
+      "expression": "type(`true`)",
+      "result": "boolean"
+    },
+    {
+      "expression": "type(`false`)",
+      "result": "boolean"
+    },
+    {
+      "expression": "type(`null`)",
+      "result": "null"
+    },
+    {
+      "expression": "type(`[0]`)",
+      "result": "array"
+    },
+    {
+      "expression": "type(`{\"a\": \"b\"}`)",
+      "result": "object"
+    },
+    {
+      "expression": "type(@)",
+      "result": "object"
+    },
+    {
+      "expression": "sort(keys(objects))",
+      "result": ["bar", "foo"]
+    },
+    {
+      "expression": "keys(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "keys(strings)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "keys(`false`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort(values(objects))",
+      "result": ["bar", "baz"]
+    },
+    {
+      "expression": "keys(empty_hash)",
+      "result": []
+    },
+    {
+      "expression": "values(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join(', ', strings)",
+      "result": "a, b, c"
+    },
+    {
+      "expression": "join(', ', strings)",
+      "result": "a, b, c"
+    },
+    {
+      "expression": "join(',', `[\"a\", \"b\"]`)",
+      "result": "a,b"
+    },
+    {
+      "expression": "join(',', `[\"a\", 0]`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join(', ', str)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join('|', strings)",
+      "result": "a|b|c"
+    },
+    {
+      "expression": "join(`2`, strings)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join('|', decimals)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join('|', decimals[].to_string(@))",
+      "result": "1.01|1.2|-1.5"
+    },
+    {
+      "expression": "join('|', empty_list)",
+      "result": ""
+    },
+    {
+      "expression": "reverse(numbers)",
+      "result": [5, 4, 3, -1]
+    },
+    {
+      "expression": "reverse(array)",
+      "result": ["100", "a", 5, 4, 3, -1]
+    },
+    {
+      "expression": "reverse(`[]`)",
+      "result": []
+    },
+    {
+      "expression": "reverse('')",
+      "result": ""
+    },
+    {
+      "expression": "reverse('hello world')",
+      "result": "dlrow olleh"
+    },
+    {
+      "expression": "starts_with(str, 'S')",
+      "result": true
+    },
+    {
+      "expression": "starts_with(str, 'St')",
+      "result": true
+    },
+    {
+      "expression": "starts_with(str, 'Str')",
+      "result": true
+    },
+    {
+      "expression": "starts_with(str, 'String')",
+      "result": false
+    },
+    {
+      "expression": "starts_with(str, `0`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sum(numbers)",
+      "result": 11
+    },
+    {
+      "expression": "sum(decimals)",
+      "result": 0.71
+    },
+    {
+      "expression": "sum(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sum(array[].to_number(@))",
+      "result": 111
+    },
+    {
+      "expression": "sum(`[]`)",
+      "result": 0
+    },
+    {
+      "expression": "to_array('foo')",
+      "result": ["foo"]
+    },
+    {
+      "expression": "to_array(`0`)",
+      "result": [0]
+    },
+    {
+      "expression": "to_array(objects)",
+      "result": [{"foo": "bar", "bar": "baz"}]
+    },
+    {
+      "expression": "to_array(`[1, 2, 3]`)",
+      "result": [1, 2, 3]
+    },
+    {
+      "expression": "to_array(false)",
+      "result": [false]
+    },
+    {
+      "expression": "to_string('foo')",
+      "result": "foo"
+    },
+    {
+      "expression": "to_string(`1.2`)",
+      "result": "1.2"
+    },
+    {
+      "expression": "to_string(`[0, 1]`)",
+      "result": "[0,1]"
+    },
+    {
+      "expression": "to_number('1.0')",
+      "result": 1.0
+    },
+    {
+      "expression": "to_number('1.1')",
+      "result": 1.1
+    },
+    {
+      "expression": "to_number('4')",
+      "result": 4
+    },
+    {
+      "expression": "to_number('notanumber')",
+      "result": null
+    },
+    {
+      "expression": "to_number(`false`)",
+      "result": null
+    },
+    {
+      "expression": "to_number(`null`)",
+      "result": null
+    },
+    {
+      "expression": "to_number(`[0]`)",
+      "result": null
+    },
+    {
+      "expression": "to_number(`{\"foo\": 0}`)",
+      "result": null
+    },
+    {
+      "expression": "\"to_string\"(`1.0`)",
+      "error": "syntax"
+    },
+    {
+      "expression": "sort(numbers)",
+      "result": [-1, 3, 4, 5]
+    },
+    {
+      "expression": "sort(strings)",
+      "result": ["a", "b", "c"]
+    },
+    {
+      "expression": "sort(decimals)",
+      "result": [-1.5, 1.01, 1.2]
+    },
+    {
+      "expression": "sort(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort(abc)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort(empty_list)",
+      "result": []
+    },
+    {
+      "expression": "sort(@)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "not_null(unknown_key, str)",
+      "result": "Str"
+    },
+    {
+      "expression": "not_null(unknown_key, foo.bar, empty_list, str)",
+      "result": []
+    },
+    {
+      "expression": "not_null(unknown_key, null_key, empty_list, str)",
+      "result": []
+    },
+    {
+      "expression": "not_null(all, expressions, are_null)",
+      "result": null
+    },
+    {
+      "expression": "not_null()",
+      "error": "invalid-arity"
+    },
+    {
+      "description": "function projection on single arg function",
+      "expression": "numbers[].to_string(@)",
+      "result": ["-1", "3", "4", "5"]
+    },
+    {
+      "description": "function projection on single arg function",
+      "expression": "array[].to_number(@)",
+      "result": [-1, 3, 4, 5, 100]
+    }
+  ]
+}, {
+  "given":
+  {
+    "foo": [
+         {"b": "b", "a": "a"},
+         {"c": "c", "b": "b"},
+         {"d": "d", "c": "c"},
+         {"e": "e", "d": "d"},
+         {"f": "f", "e": "e"}
+    ]
+  },
+  "cases": [
+    {
+      "description": "function projection on variadic function",
+      "expression": "foo[].not_null(f, e, d, c, b, a)",
+      "result": ["b", "c", "d", "e", "f"]
+    }
+  ]
+}, {
+  "given":
+  {
+    "people": [
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"},
+         {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    ]
+  },
+  "cases": [
+    {
+      "description": "sort by field expression",
+      "expression": "sort_by(people, &age)",
+      "result": [
+         {"age": 10, "age_str": "10", "bool": true, "name": 3},
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+      ]
+    },
+    {
+      "expression": "sort_by(people, &age_str)",
+      "result": [
+         {"age": 10, "age_str": "10", "bool": true, "name": 3},
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+      ]
+    },
+    {
+      "description": "sort by function expression",
+      "expression": "sort_by(people, &to_number(age_str))",
+      "result": [
+         {"age": 10, "age_str": "10", "bool": true, "name": 3},
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+      ]
+    },
+    {
+      "description": "function projection on sort_by function",
+      "expression": "sort_by(people, &age)[].name",
+      "result": [3, "a", "c", "b", "d"]
+    },
+    {
+      "expression": "sort_by(people, &extra)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, &bool)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, &name)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, name)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, &age)[].extra",
+      "result": ["foo", "bar"]
+    },
+    {
+      "expression": "sort_by(`[]`, &age)",
+      "result": []
+    },
+    {
+      "expression": "max_by(people, &age)",
+      "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+    },
+    {
+      "expression": "max_by(people, &age_str)",
+      "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+    },
+    {
+      "expression": "max_by(people, &bool)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max_by(people, &extra)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max_by(people, &to_number(age_str))",
+      "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+    },
+    {
+      "expression": "min_by(people, &age)",
+      "result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    },
+    {
+      "expression": "min_by(people, &age_str)",
+      "result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    },
+    {
+      "expression": "min_by(people, &bool)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min_by(people, &extra)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min_by(people, &to_number(age_str))",
+      "result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    }
+  ]
+}, {
+  "given":
+  {
+    "people": [
+         {"age": 10, "order": "1"},
+         {"age": 10, "order": "2"},
+         {"age": 10, "order": "3"},
+         {"age": 10, "order": "4"},
+         {"age": 10, "order": "5"},
+         {"age": 10, "order": "6"},
+         {"age": 10, "order": "7"},
+         {"age": 10, "order": "8"},
+         {"age": 10, "order": "9"},
+         {"age": 10, "order": "10"},
+         {"age": 10, "order": "11"}
+    ]
+  },
+  "cases": [
+    {
+      "description": "stable sort order",
+      "expression": "sort_by(people, &age)",
+      "result": [
+         {"age": 10, "order": "1"},
+         {"age": 10, "order": "2"},
+         {"age": 10, "order": "3"},
+         {"age": 10, "order": "4"},
+         {"age": 10, "order": "5"},
+         {"age": 10, "order": "6"},
+         {"age": 10, "order": "7"},
+         {"age": 10, "order": "8"},
+         {"age": 10, "order": "9"},
+         {"age": 10, "order": "10"},
+         {"age": 10, "order": "11"}
+      ]
+    }
+  ]
+}, {
+  "given":
+  {
+    "people": [
+         {"a": 10, "b": 1, "c": "z"},
+         {"a": 10, "b": 2, "c": null},
+         {"a": 10, "b": 3},
+         {"a": 10, "b": 4, "c": "z"},
+         {"a": 10, "b": 5, "c": null},
+         {"a": 10, "b": 6},
+         {"a": 10, "b": 7, "c": "z"},
+         {"a": 10, "b": 8, "c": null},
+         {"a": 10, "b": 9}
+    ],
+    "empty": []
+  },
+  "cases": [
+    {
+      "expression": "map(&a, people)",
+      "result": [10, 10, 10, 10, 10, 10, 10, 10, 10]
+    },
+    {
+      "expression": "map(&c, people)",
+      "result": ["z", null, null, "z", null, null, "z", null, null]
+    },
+    {
+      "expression": "map(&a, badkey)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "map(&foo, empty)",
+      "result": []
+    }
+  ]
+}, {
+  "given": {
+    "array": [
+      {
+          "foo": {"bar": "yes1"}
+      },
+      {
+          "foo": {"bar": "yes2"}
+      },
+      {
+          "foo1": {"bar": "no"}
+      }
+  ]},
+  "cases": [
+    {
+      "expression": "map(&foo.bar, array)",
+      "result": ["yes1", "yes2", null]
+    },
+    {
+      "expression": "map(&foo1.bar, array)",
+      "result": [null, null, "no"]
+    },
+    {
+      "expression": "map(&foo.bar.baz, array)",
+      "result": [null, null, null]
+    }
+  ]
+}, {
+  "given": {
+    "array": [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]]
+  },
+  "cases": [
+    {
+      "expression": "map(&[], array)",
+      "result": [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
+    }
+  ]
+}
+]

+ 1377 - 0
vendor/github.com/jmespath/go-jmespath/compliance/identifiers.json

@@ -0,0 +1,1377 @@
+[
+    {
+        "given": {
+            "__L": true
+        },
+        "cases": [
+            {
+                "expression": "__L",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"!\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Y_1623": true
+        },
+        "cases": [
+            {
+                "expression": "Y_1623",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "x": true
+        },
+        "cases": [
+            {
+                "expression": "x",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\tF\uCebb": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\tF\\uCebb\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            " \t": true
+        },
+        "cases": [
+            {
+                "expression": "\" \\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            " ": true
+        },
+        "cases": [
+            {
+                "expression": "\" \"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "v2": true
+        },
+        "cases": [
+            {
+                "expression": "v2",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_X": true
+        },
+        "cases": [
+            {
+                "expression": "_X",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t4\ud9da\udd15": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t4\\ud9da\\udd15\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "v24_W": true
+        },
+        "cases": [
+            {
+                "expression": "v24_W",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "H": true
+        },
+        "cases": [
+            {
+                "expression": "\"H\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\f": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "E4": true
+        },
+        "cases": [
+            {
+                "expression": "\"E4\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!": true
+        },
+        "cases": [
+            {
+                "expression": "\"!\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "tM": true
+        },
+        "cases": [
+            {
+                "expression": "tM",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            " [": true
+        },
+        "cases": [
+            {
+                "expression": "\" [\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "R!": true
+        },
+        "cases": [
+            {
+                "expression": "\"R!\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_6W": true
+        },
+        "cases": [
+            {
+                "expression": "_6W",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\uaBA1\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\uaBA1\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "tL7": true
+        },
+        "cases": [
+            {
+                "expression": "tL7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "<<U\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"<<U\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\ubBcE\ufAfB": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\ubBcE\\ufAfB\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "sNA_": true
+        },
+        "cases": [
+            {
+                "expression": "sNA_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "9": true
+        },
+        "cases": [
+            {
+                "expression": "\"9\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\\b\ud8cb\udc83": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\\b\\ud8cb\\udc83\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "r": true
+        },
+        "cases": [
+            {
+                "expression": "\"r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Q": true
+        },
+        "cases": [
+            {
+                "expression": "Q",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_Q__7GL8": true
+        },
+        "cases": [
+            {
+                "expression": "_Q__7GL8",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "RR9_": true
+        },
+        "cases": [
+            {
+                "expression": "RR9_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\r\f:": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\r\\f:\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "r7": true
+        },
+        "cases": [
+            {
+                "expression": "r7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "-": true
+        },
+        "cases": [
+            {
+                "expression": "\"-\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "p9": true
+        },
+        "cases": [
+            {
+                "expression": "p9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "__": true
+        },
+        "cases": [
+            {
+                "expression": "__",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "O_": true
+        },
+        "cases": [
+            {
+                "expression": "O_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_r_8": true
+        },
+        "cases": [
+            {
+                "expression": "_r_8",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_j": true
+        },
+        "cases": [
+            {
+                "expression": "_j",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ":": true
+        },
+        "cases": [
+            {
+                "expression": "\":\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\rB": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\rB\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Obf": true
+        },
+        "cases": [
+            {
+                "expression": "Obf",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\n": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\n\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\f\udb54\udf33": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\f\udb54\udf33\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\\u4FDc": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\\u4FDc\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "m_": true
+        },
+        "cases": [
+            {
+                "expression": "m_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\r\fB ": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\r\\fB \"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "+\"\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"+\\\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Mg": true
+        },
+        "cases": [
+            {
+                "expression": "Mg",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"!\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"!\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "7\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"7\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\\udb3a\udca4S": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\udb3a\udca4S\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Kl": true
+        },
+        "cases": [
+            {
+                "expression": "Kl",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b\b": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b\\b\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ">": true
+        },
+        "cases": [
+            {
+                "expression": "\">\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "hvu": true
+        },
+        "cases": [
+            {
+                "expression": "hvu",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "; !": true
+        },
+        "cases": [
+            {
+                "expression": "\"; !\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "hU": true
+        },
+        "cases": [
+            {
+                "expression": "hU",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!I\n\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"!I\\n\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\uEEbF": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\uEEbF\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "U)\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"U)\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "fa0_9": true
+        },
+        "cases": [
+            {
+                "expression": "fa0_9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "/": true
+        },
+        "cases": [
+            {
+                "expression": "\"/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Gy": true
+        },
+        "cases": [
+            {
+                "expression": "Gy",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "<": true
+        },
+        "cases": [
+            {
+                "expression": "\"<\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t&\\\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t&\\\\\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "#": true
+        },
+        "cases": [
+            {
+                "expression": "\"#\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "B__": true
+        },
+        "cases": [
+            {
+                "expression": "B__",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\nS \n": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\nS \\n\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Bp": true
+        },
+        "cases": [
+            {
+                "expression": "Bp",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ",\t;": true
+        },
+        "cases": [
+            {
+                "expression": "\",\\t;\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "B_q": true
+        },
+        "cases": [
+            {
+                "expression": "B_q",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\/+\t\n\b!Z": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\/+\\t\\n\\b!Z\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\udadd\udfc7\\ueFAc": true
+        },
+        "cases": [
+            {
+                "expression": "\"\udadd\udfc7\\\\ueFAc\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ":\f": true
+        },
+        "cases": [
+            {
+                "expression": "\":\\f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_BW_6Hg_Gl": true
+        },
+        "cases": [
+            {
+                "expression": "_BW_6Hg_Gl",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\udbcf\udc02": true
+        },
+        "cases": [
+            {
+                "expression": "\"\udbcf\udc02\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "zs1DC": true
+        },
+        "cases": [
+            {
+                "expression": "zs1DC",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "__434": true
+        },
+        "cases": [
+            {
+                "expression": "__434",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\udb94\udd41": true
+        },
+        "cases": [
+            {
+                "expression": "\"\udb94\udd41\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Z_5": true
+        },
+        "cases": [
+            {
+                "expression": "Z_5",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "z_M_": true
+        },
+        "cases": [
+            {
+                "expression": "z_M_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "YU_2": true
+        },
+        "cases": [
+            {
+                "expression": "YU_2",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_0": true
+        },
+        "cases": [
+            {
+                "expression": "_0",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b+": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b+\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "D7": true
+        },
+        "cases": [
+            {
+                "expression": "D7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_62L": true
+        },
+        "cases": [
+            {
+                "expression": "_62L",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\tK\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\tK\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\n\\\f": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\n\\\\\\f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "I_": true
+        },
+        "cases": [
+            {
+                "expression": "I_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "W_a0_": true
+        },
+        "cases": [
+            {
+                "expression": "W_a0_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "BQ": true
+        },
+        "cases": [
+            {
+                "expression": "BQ",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\tX$\uABBb": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\tX$\\uABBb\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Z9": true
+        },
+        "cases": [
+            {
+                "expression": "Z9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b%\"\uda38\udd0f": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b%\\\"\uda38\udd0f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_F": true
+        },
+        "cases": [
+            {
+                "expression": "_F",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!,": true
+        },
+        "cases": [
+            {
+                "expression": "\"!,\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"!": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"!\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Hh": true
+        },
+        "cases": [
+            {
+                "expression": "Hh",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "&": true
+        },
+        "cases": [
+            {
+                "expression": "\"&\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "9\r\\R": true
+        },
+        "cases": [
+            {
+                "expression": "\"9\\r\\\\R\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "M_k": true
+        },
+        "cases": [
+            {
+                "expression": "M_k",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!\b\n\udb06\ude52\"\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"!\\b\\n\udb06\ude52\\\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "6": true
+        },
+        "cases": [
+            {
+                "expression": "\"6\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_7": true
+        },
+        "cases": [
+            {
+                "expression": "_7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "0": true
+        },
+        "cases": [
+            {
+                "expression": "\"0\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\8\\": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\8\\\\\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "b7eo": true
+        },
+        "cases": [
+            {
+                "expression": "b7eo",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "xIUo9": true
+        },
+        "cases": [
+            {
+                "expression": "xIUo9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "5": true
+        },
+        "cases": [
+            {
+                "expression": "\"5\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "?": true
+        },
+        "cases": [
+            {
+                "expression": "\"?\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "sU": true
+        },
+        "cases": [
+            {
+                "expression": "sU",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "VH2&H\\\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"VH2&H\\\\\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_C": true
+        },
+        "cases": [
+            {
+                "expression": "_C",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_": true
+        },
+        "cases": [
+            {
+                "expression": "_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "<\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"<\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\uD834\uDD1E": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\uD834\\uDD1E\"",
+                "result": true
+            }
+        ]
+    }
+]

+ 346 - 0
vendor/github.com/jmespath/go-jmespath/compliance/indices.json

@@ -0,0 +1,346 @@
+[{
+    "given":
+        {"foo": {"bar": ["zero", "one", "two"]}},
+     "cases": [
+         {
+            "expression": "foo.bar[0]",
+            "result": "zero"
+         },
+         {
+            "expression": "foo.bar[1]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.bar[2]",
+            "result": "two"
+         },
+         {
+            "expression": "foo.bar[3]",
+            "result": null
+         },
+         {
+            "expression": "foo.bar[-1]",
+            "result": "two"
+         },
+         {
+            "expression": "foo.bar[-2]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.bar[-3]",
+            "result": "zero"
+         },
+         {
+            "expression": "foo.bar[-4]",
+            "result": null
+         }
+     ]
+},
+{
+    "given":
+        {"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
+     "cases": [
+         {
+            "expression": "foo.bar",
+            "result": null
+         },
+         {
+            "expression": "foo[0].bar",
+            "result": "one"
+         },
+         {
+            "expression": "foo[1].bar",
+            "result": "two"
+         },
+         {
+            "expression": "foo[2].bar",
+            "result": "three"
+         },
+         {
+            "expression": "foo[3].notbar",
+            "result": "four"
+         },
+         {
+            "expression": "foo[3].bar",
+            "result": null
+         },
+         {
+            "expression": "foo[0]",
+            "result": {"bar": "one"}
+         },
+         {
+            "expression": "foo[1]",
+            "result": {"bar": "two"}
+         },
+         {
+            "expression": "foo[2]",
+            "result": {"bar": "three"}
+         },
+         {
+            "expression": "foo[3]",
+            "result": {"notbar": "four"}
+         },
+         {
+            "expression": "foo[4]",
+            "result": null
+         }
+     ]
+},
+{
+    "given": [
+        "one", "two", "three"
+    ],
+     "cases": [
+         {
+            "expression": "[0]",
+            "result": "one"
+         },
+         {
+            "expression": "[1]",
+            "result": "two"
+         },
+         {
+            "expression": "[2]",
+            "result": "three"
+         },
+         {
+            "expression": "[-1]",
+            "result": "three"
+         },
+         {
+            "expression": "[-2]",
+            "result": "two"
+         },
+         {
+            "expression": "[-3]",
+            "result": "one"
+         }
+     ]
+},
+{
+    "given": {"reservations": [
+        {"instances": [{"foo": 1}, {"foo": 2}]}
+    ]},
+    "cases": [
+        {
+           "expression": "reservations[].instances[].foo",
+           "result": [1, 2]
+        },
+        {
+           "expression": "reservations[].instances[].bar",
+           "result": []
+        },
+        {
+           "expression": "reservations[].notinstances[].foo",
+           "result": []
+        },
+        {
+           "expression": "reservations[].notinstances[].foo",
+           "result": []
+        }
+    ]
+},
+{
+    "given": {"reservations": [{
+        "instances": [
+            {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
+            {"foo": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
+            {"foo": "bar"},
+            {"notfoo": [{"bar": 20}, {"bar": 21}, {"notbar": [7]}, {"bar": 22}]},
+            {"bar": [{"baz": [1]}, {"baz": [2]}, {"baz": [3]}, {"baz": [4]}]},
+            {"baz": [{"baz": [1, 2]}, {"baz": []}, {"baz": []}, {"baz": [3, 4]}]},
+            {"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
+        ],
+        "otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
+      }, {
+        "instances": [
+            {"a": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
+            {"b": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
+            {"c": "bar"},
+            {"notfoo": [{"bar": 23}, {"bar": 24}, {"notbar": [7]}, {"bar": 25}]},
+            {"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
+        ],
+        "otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
+      }
+    ]},
+    "cases": [
+        {
+           "expression": "reservations[].instances[].foo[].bar",
+           "result": [1, 2, 4, 5, 6, 8]
+        },
+        {
+           "expression": "reservations[].instances[].foo[].baz",
+           "result": []
+        },
+        {
+           "expression": "reservations[].instances[].notfoo[].bar",
+           "result": [20, 21, 22, 23, 24, 25]
+        },
+        {
+           "expression": "reservations[].instances[].notfoo[].notbar",
+           "result": [[7], [7]]
+        },
+        {
+           "expression": "reservations[].notinstances[].foo",
+           "result": []
+        },
+        {
+           "expression": "reservations[].instances[].foo[].notbar",
+           "result": [3, [7]]
+        },
+        {
+           "expression": "reservations[].instances[].bar[].baz",
+           "result": [[1], [2], [3], [4]]
+        },
+        {
+           "expression": "reservations[].instances[].baz[].baz",
+           "result": [[1, 2], [], [], [3, 4]]
+        },
+        {
+           "expression": "reservations[].instances[].qux[].baz",
+           "result": [[], [1, 2, 3], [4], [], [], [1, 2, 3], [4], []]
+        },
+        {
+           "expression": "reservations[].instances[].qux[].baz[]",
+           "result": [1, 2, 3, 4, 1, 2, 3, 4]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": [
+            [["one", "two"], ["three", "four"]],
+            [["five", "six"], ["seven", "eight"]],
+            [["nine"], ["ten"]]
+        ]
+     },
+    "cases": [
+        {
+           "expression": "foo[]",
+           "result": [["one", "two"], ["three", "four"], ["five", "six"],
+                      ["seven", "eight"], ["nine"], ["ten"]]
+        },
+        {
+           "expression": "foo[][0]",
+           "result": ["one", "three", "five", "seven", "nine", "ten"]
+        },
+        {
+           "expression": "foo[][1]",
+           "result": ["two", "four", "six", "eight"]
+        },
+        {
+           "expression": "foo[][0][0]",
+           "result": []
+        },
+         {
+            "expression": "foo[][2][2]",
+            "result": []
+         },
+         {
+            "expression": "foo[][0][0][100]",
+            "result": []
+         }
+    ]
+},
+{
+    "given": {
+      "foo": [{
+          "bar": [
+            {
+              "qux": 2,
+              "baz": 1
+            },
+            {
+              "qux": 4,
+              "baz": 3
+            }
+          ]
+        },
+        {
+          "bar": [
+            {
+              "qux": 6,
+              "baz": 5
+            },
+            {
+              "qux": 8,
+              "baz": 7
+            }
+          ]
+        }
+      ]
+    },
+    "cases": [
+        {
+           "expression": "foo",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[]",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[].bar",
+           "result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
+                      [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
+        },
+        {
+           "expression": "foo[].bar[]",
+           "result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
+                      {"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
+        },
+        {
+           "expression": "foo[].bar[].baz",
+           "result": [1, 3, 5, 7]
+        }
+    ]
+},
+{
+    "given": {
+        "string": "string",
+        "hash": {"foo": "bar", "bar": "baz"},
+        "number": 23,
+        "nullvalue": null
+     },
+     "cases": [
+         {
+            "expression": "string[]",
+            "result": null
+         },
+         {
+            "expression": "hash[]",
+            "result": null
+         },
+         {
+            "expression": "number[]",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[]",
+            "result": null
+         },
+         {
+            "expression": "string[].foo",
+            "result": null
+         },
+         {
+            "expression": "hash[].foo",
+            "result": null
+         },
+         {
+            "expression": "number[].foo",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[].foo",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[].foo[].bar",
+            "result": null
+         }
+     ]
+}
+]

+ 185 - 0
vendor/github.com/jmespath/go-jmespath/compliance/literal.json

@@ -0,0 +1,185 @@
+[
+    {
+        "given": {
+            "foo": [{"name": "a"}, {"name": "b"}],
+            "bar": {"baz": "qux"}
+        },
+        "cases": [
+            {
+                "expression": "`\"foo\"`",
+                "result": "foo"
+            },
+            {
+                "comment": "Interpret escaped unicode.",
+                "expression": "`\"\\u03a6\"`",
+                "result": "Φ"
+            },
+            {
+                "expression": "`\"✓\"`",
+                "result": "✓"
+            },
+            {
+                "expression": "`[1, 2, 3]`",
+                "result": [1, 2, 3]
+            },
+            {
+                "expression": "`{\"a\": \"b\"}`",
+                "result": {"a": "b"}
+            },
+            {
+                "expression": "`true`",
+                "result": true
+            },
+            {
+                "expression": "`false`",
+                "result": false
+            },
+            {
+                "expression": "`null`",
+                "result": null
+            },
+            {
+                "expression": "`0`",
+                "result": 0
+            },
+            {
+                "expression": "`1`",
+                "result": 1
+            },
+            {
+                "expression": "`2`",
+                "result": 2
+            },
+            {
+                "expression": "`3`",
+                "result": 3
+            },
+            {
+                "expression": "`4`",
+                "result": 4
+            },
+            {
+                "expression": "`5`",
+                "result": 5
+            },
+            {
+                "expression": "`6`",
+                "result": 6
+            },
+            {
+                "expression": "`7`",
+                "result": 7
+            },
+            {
+                "expression": "`8`",
+                "result": 8
+            },
+            {
+                "expression": "`9`",
+                "result": 9
+            },
+            {
+                "comment": "Escaping a backtick in quotes",
+                "expression": "`\"foo\\`bar\"`",
+                "result": "foo`bar"
+            },
+            {
+                "comment": "Double quote in literal",
+                "expression": "`\"foo\\\"bar\"`",
+                "result": "foo\"bar"
+            },
+            {
+                "expression": "`\"1\\`\"`",
+                "result": "1`"
+            },
+            {
+                "comment": "Multiple literal expressions with escapes",
+                "expression": "`\"\\\\\"`.{a:`\"b\"`}",
+                "result": {"a": "b"}
+            },
+            {
+                "comment": "literal . identifier",
+                "expression": "`{\"a\": \"b\"}`.a",
+                "result": "b"
+            },
+            {
+                "comment": "literal . identifier . identifier",
+                "expression": "`{\"a\": {\"b\": \"c\"}}`.a.b",
+                "result": "c"
+            },
+            {
+                "comment": "literal . identifier bracket-expr",
+                "expression": "`[0, 1, 2]`[1]",
+                "result": 1
+            }
+        ]
+    },
+    {
+      "comment": "Literals",
+      "given": {"type": "object"},
+      "cases": [
+        {
+          "comment": "Literal with leading whitespace",
+          "expression": "`  {\"foo\": true}`",
+          "result": {"foo": true}
+        },
+        {
+          "comment": "Literal with trailing whitespace",
+          "expression": "`{\"foo\": true}   `",
+          "result": {"foo": true}
+        },
+        {
+          "comment": "Literal on RHS of subexpr not allowed",
+          "expression": "foo.`\"bar\"`",
+          "error": "syntax"
+        }
+      ]
+    },
+    {
+      "comment": "Raw String Literals",
+      "given": {},
+      "cases": [
+        {
+          "expression": "'foo'",
+          "result": "foo"
+        },
+        {
+          "expression": "'  foo  '",
+          "result": "  foo  "
+        },
+        {
+          "expression": "'0'",
+          "result": "0"
+        },
+        {
+          "expression": "'newline\n'",
+          "result": "newline\n"
+        },
+        {
+          "expression": "'\n'",
+          "result": "\n"
+        },
+        {
+          "expression": "'✓'",
+	  "result": "✓"
+        },
+        {
+          "expression": "'𝄞'",
+	  "result": "𝄞"
+        },
+        {
+          "expression": "'  [foo]  '",
+          "result": "  [foo]  "
+        },
+        {
+          "expression": "'[foo]'",
+          "result": "[foo]"
+        },
+        {
+          "comment": "Do not interpret escaped unicode.",
+          "expression": "'\\u03a6'",
+          "result": "\\u03a6"
+        }
+      ]
+    }
+]

+ 393 - 0
vendor/github.com/jmespath/go-jmespath/compliance/multiselect.json

@@ -0,0 +1,393 @@
+[{
+    "given": {
+      "foo": {
+        "bar": "bar",
+        "baz": "baz",
+        "qux": "qux",
+        "nested": {
+          "one": {
+            "a": "first",
+            "b": "second",
+            "c": "third"
+          },
+          "two": {
+            "a": "first",
+            "b": "second",
+            "c": "third"
+          },
+          "three": {
+            "a": "first",
+            "b": "second",
+            "c": {"inner": "third"}
+          }
+        }
+      },
+      "bar": 1,
+      "baz": 2,
+      "qux\"": 3
+    },
+     "cases": [
+         {
+            "expression": "foo.{bar: bar}",
+            "result": {"bar": "bar"}
+         },
+         {
+            "expression": "foo.{\"bar\": bar}",
+            "result": {"bar": "bar"}
+         },
+         {
+            "expression": "foo.{\"foo.bar\": bar}",
+            "result": {"foo.bar": "bar"}
+         },
+         {
+            "expression": "foo.{bar: bar, baz: baz}",
+            "result": {"bar": "bar", "baz": "baz"}
+         },
+         {
+            "expression": "foo.{\"bar\": bar, \"baz\": baz}",
+            "result": {"bar": "bar", "baz": "baz"}
+         },
+         {
+            "expression": "{\"baz\": baz, \"qux\\\"\": \"qux\\\"\"}",
+            "result": {"baz": 2, "qux\"": 3}
+         },
+         {
+            "expression": "foo.{bar:bar,baz:baz}",
+            "result": {"bar": "bar", "baz": "baz"}
+         },
+         {
+            "expression": "foo.{bar: bar,qux: qux}",
+            "result": {"bar": "bar", "qux": "qux"}
+         },
+         {
+            "expression": "foo.{bar: bar, noexist: noexist}",
+            "result": {"bar": "bar", "noexist": null}
+         },
+         {
+            "expression": "foo.{noexist: noexist, alsonoexist: alsonoexist}",
+            "result": {"noexist": null, "alsonoexist": null}
+         },
+         {
+            "expression": "foo.badkey.{nokey: nokey, alsonokey: alsonokey}",
+            "result": null
+         },
+         {
+            "expression": "foo.nested.*.{a: a,b: b}",
+            "result": [{"a": "first", "b": "second"},
+                       {"a": "first", "b": "second"},
+                       {"a": "first", "b": "second"}]
+         },
+         {
+            "expression": "foo.nested.three.{a: a, cinner: c.inner}",
+            "result": {"a": "first", "cinner": "third"}
+         },
+         {
+            "expression": "foo.nested.three.{a: a, c: c.inner.bad.key}",
+            "result": {"a": "first", "c": null}
+         },
+         {
+            "expression": "foo.{a: nested.one.a, b: nested.two.b}",
+            "result": {"a": "first", "b": "second"}
+         },
+         {
+            "expression": "{bar: bar, baz: baz}",
+            "result": {"bar": 1, "baz": 2}
+         },
+         {
+            "expression": "{bar: bar}",
+            "result": {"bar": 1}
+         },
+         {
+            "expression": "{otherkey: bar}",
+            "result": {"otherkey": 1}
+         },
+         {
+            "expression": "{no: no, exist: exist}",
+            "result": {"no": null, "exist": null}
+         },
+         {
+            "expression": "foo.[bar]",
+            "result": ["bar"]
+         },
+         {
+            "expression": "foo.[bar,baz]",
+            "result": ["bar", "baz"]
+         },
+         {
+            "expression": "foo.[bar,qux]",
+            "result": ["bar", "qux"]
+         },
+         {
+            "expression": "foo.[bar,noexist]",
+            "result": ["bar", null]
+         },
+         {
+            "expression": "foo.[noexist,alsonoexist]",
+            "result": [null, null]
+         }
+     ]
+}, {
+    "given": {
+      "foo": {"bar": 1, "baz": [2, 3, 4]}
+    },
+    "cases": [
+         {
+            "expression": "foo.{bar:bar,baz:baz}",
+            "result": {"bar": 1, "baz": [2, 3, 4]}
+         },
+         {
+            "expression": "foo.[bar,baz[0]]",
+            "result": [1, 2]
+         },
+         {
+            "expression": "foo.[bar,baz[1]]",
+            "result": [1, 3]
+         },
+         {
+            "expression": "foo.[bar,baz[2]]",
+            "result": [1, 4]
+         },
+         {
+            "expression": "foo.[bar,baz[3]]",
+            "result": [1, null]
+         },
+         {
+            "expression": "foo.[bar[0],baz[3]]",
+            "result": [null, null]
+         }
+    ]
+}, {
+    "given": {
+      "foo": {"bar": 1, "baz": 2}
+    },
+    "cases": [
+         {
+            "expression": "foo.{bar: bar, baz: baz}",
+            "result": {"bar": 1, "baz": 2}
+         },
+         {
+            "expression": "foo.[bar,baz]",
+            "result": [1, 2]
+         }
+    ]
+}, {
+    "given": {
+      "foo": {
+          "bar": {"baz": [{"common": "first", "one": 1},
+                          {"common": "second", "two": 2}]},
+          "ignoreme": 1,
+          "includeme": true
+      }
+    },
+    "cases": [
+         {
+            "expression": "foo.{bar: bar.baz[1],includeme: includeme}",
+            "result": {"bar": {"common": "second", "two": 2}, "includeme": true}
+         },
+         {
+            "expression": "foo.{\"bar.baz.two\": bar.baz[1].two, includeme: includeme}",
+            "result": {"bar.baz.two": 2, "includeme": true}
+         },
+         {
+            "expression": "foo.[includeme, bar.baz[*].common]",
+            "result": [true, ["first", "second"]]
+         },
+         {
+            "expression": "foo.[includeme, bar.baz[*].none]",
+            "result": [true, []]
+         },
+         {
+            "expression": "foo.[includeme, bar.baz[].common]",
+            "result": [true, ["first", "second"]]
+         }
+    ]
+}, {
+    "given": {
+      "reservations": [{
+          "instances": [
+              {"id": "id1",
+               "name": "first"},
+              {"id": "id2",
+               "name": "second"}
+          ]}, {
+          "instances": [
+              {"id": "id3",
+               "name": "third"},
+              {"id": "id4",
+               "name": "fourth"}
+          ]}
+      ]},
+    "cases": [
+         {
+            "expression": "reservations[*].instances[*].{id: id, name: name}",
+            "result": [[{"id": "id1", "name": "first"}, {"id": "id2", "name": "second"}],
+                       [{"id": "id3", "name": "third"}, {"id": "id4", "name": "fourth"}]]
+         },
+         {
+            "expression": "reservations[].instances[].{id: id, name: name}",
+            "result": [{"id": "id1", "name": "first"},
+                       {"id": "id2", "name": "second"},
+                       {"id": "id3", "name": "third"},
+                       {"id": "id4", "name": "fourth"}]
+         },
+         {
+            "expression": "reservations[].instances[].[id, name]",
+            "result": [["id1", "first"],
+                       ["id2", "second"],
+                       ["id3", "third"],
+                       ["id4", "fourth"]]
+         }
+    ]
+},
+{
+    "given": {
+      "foo": [{
+          "bar": [
+            {
+              "qux": 2,
+              "baz": 1
+            },
+            {
+              "qux": 4,
+              "baz": 3
+            }
+          ]
+        },
+        {
+          "bar": [
+            {
+              "qux": 6,
+              "baz": 5
+            },
+            {
+              "qux": 8,
+              "baz": 7
+            }
+          ]
+        }
+      ]
+    },
+    "cases": [
+        {
+           "expression": "foo",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[]",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[].bar",
+           "result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
+                      [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
+        },
+        {
+           "expression": "foo[].bar[]",
+           "result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
+                      {"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
+        },
+        {
+           "expression": "foo[].bar[].[baz, qux]",
+           "result": [[1, 2], [3, 4], [5, 6], [7, 8]]
+        },
+        {
+           "expression": "foo[].bar[].[baz]",
+           "result": [[1], [3], [5], [7]]
+        },
+        {
+           "expression": "foo[].bar[].[baz, qux][]",
+           "result": [1, 2, 3, 4, 5, 6, 7, 8]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": {
+            "baz": [
+                {
+                    "bar": "abc"
+                }, {
+                    "bar": "def"
+                }
+            ],
+            "qux": ["zero"]
+        }
+    },
+    "cases": [
+        {
+           "expression": "foo.[baz[*].bar, qux[0]]",
+           "result": [["abc", "def"], "zero"]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": {
+            "baz": [
+                {
+                    "bar": "a",
+                    "bam": "b",
+                    "boo": "c"
+                }, {
+                    "bar": "d",
+                    "bam": "e",
+                    "boo": "f"
+                }
+            ],
+            "qux": ["zero"]
+        }
+    },
+    "cases": [
+        {
+           "expression": "foo.[baz[*].[bar, boo], qux[0]]",
+           "result": [[["a", "c" ], ["d", "f" ]], "zero"]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": {
+            "baz": [
+                {
+                    "bar": "a",
+                    "bam": "b",
+                    "boo": "c"
+                }, {
+                    "bar": "d",
+                    "bam": "e",
+                    "boo": "f"
+                }
+            ],
+            "qux": ["zero"]
+        }
+    },
+    "cases": [
+        {
+           "expression": "foo.[baz[*].not_there || baz[*].bar, qux[0]]",
+           "result": [["a", "d"], "zero"]
+        }
+    ]
+},
+{
+    "given": {"type": "object"},
+    "cases": [
+        {
+          "comment": "Nested multiselect",
+          "expression": "[[*],*]",
+          "result": [null, ["object"]]
+        }
+    ]
+},
+{
+    "given": [],
+    "cases": [
+        {
+          "comment": "Nested multiselect",
+          "expression": "[[*]]",
+          "result": [[]]
+        }
+    ]
+}
+]

+ 59 - 0
vendor/github.com/jmespath/go-jmespath/compliance/ormatch.json

@@ -0,0 +1,59 @@
+[{
+    "given":
+        {"outer": {"foo": "foo", "bar": "bar", "baz": "baz"}},
+     "cases": [
+         {
+            "expression": "outer.foo || outer.bar",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.foo||outer.bar",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.bar || outer.baz",
+            "result": "bar"
+         },
+         {
+            "expression": "outer.bar||outer.baz",
+            "result": "bar"
+         },
+         {
+            "expression": "outer.bad || outer.foo",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.bad||outer.foo",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.foo || outer.bad",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.foo||outer.bad",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.bad || outer.alsobad",
+            "result": null
+         },
+         {
+            "expression": "outer.bad||outer.alsobad",
+            "result": null
+         }
+     ]
+}, {
+    "given":
+        {"outer": {"foo": "foo", "bool": false, "empty_list": [], "empty_string": ""}},
+     "cases": [
+         {
+            "expression": "outer.empty_string || outer.foo",
+            "result": "foo"
+         },
+         {
+            "expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo",
+            "result": "foo"
+         }
+     ]
+}]

+ 131 - 0
vendor/github.com/jmespath/go-jmespath/compliance/pipe.json

@@ -0,0 +1,131 @@
+[{
+  "given": {
+    "foo": {
+      "bar": {
+        "baz": "subkey"
+      },
+      "other": {
+        "baz": "subkey"
+      },
+      "other2": {
+        "baz": "subkey"
+      },
+      "other3": {
+        "notbaz": ["a", "b", "c"]
+      },
+      "other4": {
+        "notbaz": ["a", "b", "c"]
+      }
+    }
+  },
+  "cases": [
+    {
+      "expression": "foo.*.baz | [0]",
+      "result": "subkey"
+    },
+    {
+      "expression": "foo.*.baz | [1]",
+      "result": "subkey"
+    },
+    {
+      "expression": "foo.*.baz | [2]",
+      "result": "subkey"
+    },
+    {
+      "expression": "foo.bar.* | [0]",
+      "result": "subkey"
+    },
+    {
+      "expression": "foo.*.notbaz | [*]",
+      "result": [["a", "b", "c"], ["a", "b", "c"]]
+    },
+    {
+      "expression": "{\"a\": foo.bar, \"b\": foo.other} | *.baz",
+      "result": ["subkey", "subkey"]
+    }
+  ]
+}, {
+  "given": {
+    "foo": {
+      "bar": {
+        "baz": "one"
+      },
+      "other": {
+        "baz": "two"
+      },
+      "other2": {
+        "baz": "three"
+      },
+      "other3": {
+        "notbaz": ["a", "b", "c"]
+      },
+      "other4": {
+        "notbaz": ["d", "e", "f"]
+      }
+    }
+  },
+  "cases": [
+    {
+      "expression": "foo | bar",
+      "result": {"baz": "one"}
+    },
+    {
+      "expression": "foo | bar | baz",
+      "result": "one"
+    },
+    {
+      "expression": "foo|bar| baz",
+      "result": "one"
+    },
+    {
+      "expression": "not_there | [0]",
+      "result": null
+    },
+    {
+      "expression": "not_there | [0]",
+      "result": null
+    },
+    {
+      "expression": "[foo.bar, foo.other] | [0]",
+      "result": {"baz": "one"}
+    },
+    {
+      "expression": "{\"a\": foo.bar, \"b\": foo.other} | a",
+      "result": {"baz": "one"}
+    },
+    {
+      "expression": "{\"a\": foo.bar, \"b\": foo.other} | b",
+      "result": {"baz": "two"}
+    },
+    {
+      "expression": "foo.bam || foo.bar | baz",
+      "result": "one"
+    },
+    {
+      "expression": "foo | not_there || bar",
+      "result": {"baz": "one"}
+    }
+  ]
+}, {
+  "given": {
+    "foo": [{
+      "bar": [{
+        "baz": "one"
+      }, {
+        "baz": "two"
+      }]
+    }, {
+      "bar": [{
+        "baz": "three"
+      }, {
+        "baz": "four"
+      }]
+    }]
+  },
+  "cases": [
+    {
+      "expression": "foo[*].bar[*] | [0][0]",
+      "result": {"baz": "one"}
+    }
+  ]
+}]

+ 187 - 0
vendor/github.com/jmespath/go-jmespath/compliance/slice.json

@@ -0,0 +1,187 @@
+[{
+  "given": {
+    "foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+    "bar": {
+      "baz": 1
+    }
+  },
+  "cases": [
+    {
+      "expression": "bar[0:10]",
+      "result": null
+    },
+    {
+      "expression": "foo[0:10:1]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[0:10]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[0:10:]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[0::1]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[0::]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[0:]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[:10:1]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[::1]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[:10:]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[::]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[:]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[1:9]",
+      "result": [1, 2, 3, 4, 5, 6, 7, 8]
+    },
+    {
+      "expression": "foo[0:10:2]",
+      "result": [0, 2, 4, 6, 8]
+    },
+    {
+      "expression": "foo[5:]",
+      "result": [5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[5::2]",
+      "result": [5, 7, 9]
+    },
+    {
+      "expression": "foo[::2]",
+      "result": [0, 2, 4, 6, 8]
+    },
+    {
+      "expression": "foo[::-1]",
+      "result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+    },
+    {
+      "expression": "foo[1::2]",
+      "result": [1, 3, 5, 7, 9]
+    },
+    {
+      "expression": "foo[10:0:-1]",
+      "result": [9, 8, 7, 6, 5, 4, 3, 2, 1]
+    },
+    {
+      "expression": "foo[10:5:-1]",
+      "result": [9, 8, 7, 6]
+    },
+    {
+      "expression": "foo[8:2:-2]",
+      "result": [8, 6, 4]
+    },
+    {
+      "expression": "foo[0:20]",
+      "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    {
+      "expression": "foo[10:-20:-1]",
+      "result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+    },
+    {
+      "expression": "foo[10:-20]",
+      "result": []
+    },
+    {
+      "expression": "foo[-4:-1]",
+      "result": [6, 7, 8]
+    },
+    {
+      "expression": "foo[:-5:-1]",
+      "result": [9, 8, 7, 6]
+    },
+    {
+      "expression": "foo[8:2:0]",
+      "error": "invalid-value"
+    },
+    {
+      "expression": "foo[8:2:0:1]",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo[8:2&]",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo[2:a:3]",
+      "error": "syntax"
+    }
+  ]
+}, {
+  "given": {
+    "foo": [{"a": 1}, {"a": 2}, {"a": 3}],
+    "bar": [{"a": {"b": 1}}, {"a": {"b": 2}},
+	    {"a": {"b": 3}}],
+    "baz": 50
+  },
+  "cases": [
+    {
+      "expression": "foo[:2].a",
+      "result": [1, 2]
+    },
+    {
+      "expression": "foo[:2].b",
+      "result": []
+    },
+    {
+      "expression": "foo[:2].a.b",
+      "result": []
+    },
+    {
+      "expression": "bar[::-1].a.b",
+      "result": [3, 2, 1]
+    },
+    {
+      "expression": "bar[:2].a.b",
+      "result": [1, 2]
+    },
+    {
+      "expression": "baz[:2].a",
+      "result": null
+    }
+  ]
+}, {
+  "given": [{"a": 1}, {"a": 2}, {"a": 3}],
+  "cases": [
+    {
+      "expression": "[:]",
+      "result": [{"a": 1}, {"a": 2}, {"a": 3}]
+    },
+    {
+      "expression": "[:2].a",
+      "result": [1, 2]
+    },
+    {
+      "expression": "[::-1].a",
+      "result": [3, 2, 1]
+    },
+    {
+      "expression": "[:2].b",
+      "result": []
+    }
+  ]
+}]

+ 616 - 0
vendor/github.com/jmespath/go-jmespath/compliance/syntax.json

@@ -0,0 +1,616 @@
+[{
+  "comment": "Dot syntax",
+  "given": {"type": "object"},
+  "cases": [
+    {
+      "expression": "foo.bar",
+      "result": null
+    },
+    {
+      "expression": "foo.1",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo.-11",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo",
+      "result": null
+    },
+    {
+      "expression": "foo.",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo.",
+      "error": "syntax"
+    },
+    {
+      "expression": ".foo",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo..bar",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo.bar.",
+      "error": "syntax"
+    },
+    {
+      "expression": "foo[.]",
+      "error": "syntax"
+    }
+  ]
+},
+  {
+    "comment": "Simple token errors",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": ".",
+        "error": "syntax"
+      },
+      {
+        "expression": ":",
+        "error": "syntax"
+      },
+      {
+        "expression": ",",
+        "error": "syntax"
+      },
+      {
+        "expression": "]",
+        "error": "syntax"
+      },
+      {
+        "expression": "[",
+        "error": "syntax"
+      },
+      {
+        "expression": "}",
+        "error": "syntax"
+      },
+      {
+        "expression": "{",
+        "error": "syntax"
+      },
+      {
+        "expression": ")",
+        "error": "syntax"
+      },
+      {
+        "expression": "(",
+        "error": "syntax"
+      },
+      {
+        "expression": "((&",
+        "error": "syntax"
+      },
+      {
+        "expression": "a[",
+        "error": "syntax"
+      },
+      {
+        "expression": "a]",
+        "error": "syntax"
+      },
+      {
+        "expression": "a][",
+        "error": "syntax"
+      },
+      {
+        "expression": "!",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Boolean syntax errors",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "![!(!",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Wildcard syntax",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "*",
+        "result": ["object"]
+      },
+      {
+        "expression": "*.*",
+        "result": []
+      },
+      {
+        "expression": "*.foo",
+        "result": []
+      },
+      {
+        "expression": "*[0]",
+        "result": []
+      },
+      {
+        "expression": ".*",
+        "error": "syntax"
+      },
+      {
+        "expression": "*foo",
+        "error": "syntax"
+      },
+      {
+        "expression": "*0",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[*]bar",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[*]*",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Flatten syntax",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "[]",
+        "result": null
+      }
+    ]
+  },
+  {
+    "comment": "Simple bracket syntax",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "[0]",
+        "result": null
+      },
+      {
+        "expression": "[*]",
+        "result": null
+      },
+      {
+        "expression": "*.[0]",
+        "error": "syntax"
+      },
+      {
+        "expression": "*.[\"0\"]",
+        "result": [[null]]
+      },
+      {
+        "expression": "[*].bar",
+        "result": null
+      },
+      {
+        "expression": "[*][0]",
+        "result": null
+      },
+      {
+        "expression": "foo[#]",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Multi-select list syntax",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "foo[0]",
+        "result": null
+      },
+      {
+        "comment": "Valid multi-select of a list",
+        "expression": "foo[0, 1]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo.[0]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo.[*]",
+        "result": null
+      },
+      {
+        "comment": "Multi-select of a list with trailing comma",
+        "expression": "foo[0, ]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list with trailing comma and no close",
+        "expression": "foo[0,",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list with trailing comma and no close",
+        "expression": "foo.[a",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list with extra comma",
+        "expression": "foo[0,, 1]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list using an identifier index",
+        "expression": "foo[abc]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list using identifier indices",
+        "expression": "foo[abc, def]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list using an identifier index",
+        "expression": "foo[abc, 1]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a list using an identifier index with trailing comma",
+        "expression": "foo[abc, ]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Valid multi-select of a hash using an identifier index",
+        "expression": "foo.[abc]",
+        "result": null
+      },
+      {
+        "comment": "Valid multi-select of a hash",
+        "expression": "foo.[abc, def]",
+        "result": null
+      },
+      {
+        "comment": "Multi-select of a hash using a numeric index",
+        "expression": "foo.[abc, 1]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a hash with a trailing comma",
+        "expression": "foo.[abc, ]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a hash with extra commas",
+        "expression": "foo.[abc,, def]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Multi-select of a hash using number indices",
+        "expression": "foo.[0, 1]",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Multi-select hash syntax",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "comment": "No key or value",
+        "expression": "a{}",
+        "error": "syntax"
+      },
+      {
+        "comment": "No closing token",
+        "expression": "a{",
+        "error": "syntax"
+      },
+      {
+        "comment": "Not a key value pair",
+        "expression": "a{foo}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing value and closing character",
+        "expression": "a{foo:",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing closing character",
+        "expression": "a{foo: 0",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing value",
+        "expression": "a{foo:}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Trailing comma and no closing character",
+        "expression": "a{foo: 0, ",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing value with trailing comma",
+        "expression": "a{foo: ,}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Accessing Array using an identifier",
+        "expression": "a{foo: bar}",
+        "error": "syntax"
+      },
+      {
+        "expression": "a{foo: 0}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing key-value pair",
+        "expression": "a.{}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Not a key-value pair",
+        "expression": "a.{foo}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing value",
+        "expression": "a.{foo:}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing value with trailing comma",
+        "expression": "a.{foo: ,}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Valid multi-select hash extraction",
+        "expression": "a.{foo: bar}",
+        "result": null
+      },
+      {
+        "comment": "Valid multi-select hash extraction",
+        "expression": "a.{foo: bar, baz: bam}",
+        "result": null
+      },
+      {
+        "comment": "Trailing comma",
+        "expression": "a.{foo: bar, }",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing key in second key-value pair",
+        "expression": "a.{foo: bar, baz}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Missing value in second key-value pair",
+        "expression": "a.{foo: bar, baz:}",
+        "error": "syntax"
+      },
+      {
+        "comment": "Trailing comma",
+        "expression": "a.{foo: bar, baz: bam, }",
+        "error": "syntax"
+      },
+      {
+        "comment": "Nested multi select",
+        "expression": "{\"\\\\\":{\" \":*}}",
+        "result": {"\\": {" ": ["object"]}}
+      }
+    ]
+  },
+  {
+    "comment": "Or expressions",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "foo || bar",
+        "result": null
+      },
+      {
+        "expression": "foo ||",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo.|| bar",
+        "error": "syntax"
+      },
+      {
+        "expression": " || foo",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo || || foo",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo.[a || b]",
+        "result": null
+      },
+      {
+        "expression": "foo.[a ||]",
+        "error": "syntax"
+      },
+      {
+        "expression": "\"foo",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Filter expressions",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "foo[?bar==`\"baz\"`]",
+        "result": null
+      },
+      {
+        "expression": "foo[? bar == `\"baz\"` ]",
+        "result": null
+      },
+      {
+        "expression": "foo[ ?bar==`\"baz\"`]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[?bar==]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[?==]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[?==bar]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[?bar==baz?]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[?a.b.c==d.e.f]",
+        "result": null
+      },
+      {
+        "expression": "foo[?bar==`[0, 1, 2]`]",
+        "result": null
+      },
+      {
+        "expression": "foo[?bar==`[\"a\", \"b\", \"c\"]`]",
+        "result": null
+      },
+      {
+        "comment": "Literal char not escaped",
+        "expression": "foo[?bar==`[\"foo`bar\"]`]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Literal char escaped",
+        "expression": "foo[?bar==`[\"foo\\`bar\"]`]",
+        "result": null
+      },
+      {
+        "comment": "Unknown comparator",
+        "expression": "foo[?bar<>baz]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Unknown comparator",
+        "expression": "foo[?bar^baz]",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[bar==baz]",
+        "error": "syntax"
+      },
+      {
+        "comment": "Quoted identifier in filter expression no spaces",
+        "expression": "[?\"\\\\\">`\"foo\"`]",
+        "result": null
+      },
+      {
+        "comment": "Quoted identifier in filter expression with spaces",
+        "expression": "[?\"\\\\\" > `\"foo\"`]",
+        "result": null
+      }
+    ]
+  },
+  {
+    "comment": "Filter expression errors",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "bar.`\"anything\"`",
+        "error": "syntax"
+      },
+      {
+        "expression": "bar.baz.noexists.`\"literal\"`",
+        "error": "syntax"
+      },
+      {
+        "comment": "Literal wildcard projection",
+        "expression": "foo[*].`\"literal\"`",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[*].name.`\"literal\"`",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[].name.`\"literal\"`",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[].name.`\"literal\"`.`\"subliteral\"`",
+        "error": "syntax"
+      },
+      {
+        "comment": "Projecting a literal onto an empty list",
+        "expression": "foo[*].name.noexist.`\"literal\"`",
+        "error": "syntax"
+      },
+      {
+        "expression": "foo[].name.noexist.`\"literal\"`",
+        "error": "syntax"
+      },
+      {
+        "expression": "twolen[*].`\"foo\"`",
+        "error": "syntax"
+      },
+      {
+        "comment": "Two level projection of a literal",
+        "expression": "twolen[*].threelen[*].`\"bar\"`",
+        "error": "syntax"
+      },
+      {
+        "comment": "Two level flattened projection of a literal",
+        "expression": "twolen[].threelen[].`\"bar\"`",
+        "error": "syntax"
+      }
+    ]
+  },
+  {
+    "comment": "Identifiers",
+    "given": {"type": "object"},
+    "cases": [
+      {
+        "expression": "foo",
+        "result": null
+      },
+      {
+        "expression": "\"foo\"",
+        "result": null
+      },
+      {
+        "expression": "\"\\\\\"",
+        "result": null
+      }
+    ]
+  },
+  {
+    "comment": "Combined syntax",
+    "given": [],
+    "cases": [
+        {
+          "expression": "*||*|*|*",
+          "result": null
+        },
+        {
+          "expression": "*[]||[*]",
+          "result": []
+        },
+        {
+          "expression": "[*.*]",
+          "result": [null]
+        }
+    ]
+  }
+]

+ 38 - 0
vendor/github.com/jmespath/go-jmespath/compliance/unicode.json

@@ -0,0 +1,38 @@
+[
+    {
+        "given": {"foo": [{"✓": "✓"}, {"✓": "✗"}]},
+        "cases": [
+            {
+                "expression": "foo[].\"✓\"",
+                "result": ["✓", "✗"]
+            }
+        ]
+    },
+    {
+        "given": {"☯": true},
+        "cases": [
+            {
+                "expression": "\"☯\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪": true},
+        "cases": [
+            {
+                "expression": "\"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {"☃": true},
+        "cases": [
+            {
+                "expression": "\"☃\"",
+                "result": true
+            }
+        ]
+    }
+]

+ 460 - 0
vendor/github.com/jmespath/go-jmespath/compliance/wildcard.json

@@ -0,0 +1,460 @@
+[{
+    "given": {
+        "foo": {
+            "bar": {
+                "baz": "val"
+            },
+            "other": {
+                "baz": "val"
+            },
+            "other2": {
+                "baz": "val"
+            },
+            "other3": {
+                "notbaz": ["a", "b", "c"]
+            },
+            "other4": {
+                "notbaz": ["a", "b", "c"]
+            },
+            "other5": {
+                "other": {
+                    "a": 1,
+                    "b": 1,
+                    "c": 1
+                }
+            }
+        }
+    },
+    "cases": [
+         {
+            "expression": "foo.*.baz",
+            "result": ["val", "val", "val"]
+         },
+         {
+            "expression": "foo.bar.*",
+            "result": ["val"]
+         },
+         {
+            "expression": "foo.*.notbaz",
+            "result": [["a", "b", "c"], ["a", "b", "c"]]
+         },
+         {
+            "expression": "foo.*.notbaz[0]",
+            "result": ["a", "a"]
+         },
+         {
+            "expression": "foo.*.notbaz[-1]",
+            "result": ["c", "c"]
+         }
+    ]
+}, {
+    "given": {
+        "foo": {
+            "first-1": {
+                "second-1": "val"
+            },
+            "first-2": {
+                "second-1": "val"
+            },
+            "first-3": {
+                "second-1": "val"
+            }
+        }
+    },
+    "cases": [
+         {
+            "expression": "foo.*",
+            "result": [{"second-1": "val"}, {"second-1": "val"},
+                       {"second-1": "val"}]
+         },
+         {
+            "expression": "foo.*.*",
+            "result": [["val"], ["val"], ["val"]]
+         },
+         {
+            "expression": "foo.*.*.*",
+            "result": [[], [], []]
+         },
+         {
+            "expression": "foo.*.*.*.*",
+            "result": [[], [], []]
+         }
+    ]
+}, {
+    "given": {
+        "foo": {
+            "bar": "one"
+        },
+        "other": {
+            "bar": "one"
+        },
+        "nomatch": {
+            "notbar": "three"
+        }
+    },
+    "cases": [
+         {
+            "expression": "*.bar",
+            "result": ["one", "one"]
+         }
+    ]
+}, {
+    "given": {
+        "top1": {
+            "sub1": {"foo": "one"}
+        },
+        "top2": {
+            "sub1": {"foo": "one"}
+        }
+    },
+    "cases": [
+         {
+            "expression": "*",
+            "result": [{"sub1": {"foo": "one"}},
+                       {"sub1": {"foo": "one"}}]
+         },
+         {
+            "expression": "*.sub1",
+            "result": [{"foo": "one"},
+                       {"foo": "one"}]
+         },
+         {
+            "expression": "*.*",
+            "result": [[{"foo": "one"}],
+                       [{"foo": "one"}]]
+         },
+         {
+            "expression": "*.*.foo[]",
+            "result": ["one", "one"]
+         },
+         {
+            "expression": "*.sub1.foo",
+            "result": ["one", "one"]
+         }
+    ]
+},
+{
+    "given":
+        {"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
+     "cases": [
+         {
+            "expression": "foo[*].bar",
+            "result": ["one", "two", "three"]
+         },
+         {
+            "expression": "foo[*].notbar",
+            "result": ["four"]
+         }
+     ]
+},
+{
+    "given":
+        [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}],
+     "cases": [
+         {
+            "expression": "[*]",
+            "result": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]
+         },
+         {
+            "expression": "[*].bar",
+            "result": ["one", "two", "three"]
+         },
+         {
+            "expression": "[*].notbar",
+            "result": ["four"]
+         }
+     ]
+},
+{
+    "given": {
+        "foo": {
+            "bar": [
+                {"baz": ["one", "two", "three"]},
+                {"baz": ["four", "five", "six"]},
+                {"baz": ["seven", "eight", "nine"]}
+            ]
+        }
+    },
+     "cases": [
+         {
+            "expression": "foo.bar[*].baz",
+            "result": [["one", "two", "three"], ["four", "five", "six"], ["seven", "eight", "nine"]]
+         },
+         {
+            "expression": "foo.bar[*].baz[0]",
+            "result": ["one", "four", "seven"]
+         },
+         {
+            "expression": "foo.bar[*].baz[1]",
+            "result": ["two", "five", "eight"]
+         },
+         {
+            "expression": "foo.bar[*].baz[2]",
+            "result": ["three", "six", "nine"]
+         },
+         {
+            "expression": "foo.bar[*].baz[3]",
+            "result": []
+         }
+     ]
+},
+{
+    "given": {
+        "foo": {
+            "bar": [["one", "two"], ["three", "four"]]
+        }
+    },
+     "cases": [
+         {
+            "expression": "foo.bar[*]",
+            "result": [["one", "two"], ["three", "four"]]
+         },
+         {
+            "expression": "foo.bar[0]",
+            "result": ["one", "two"]
+         },
+         {
+            "expression": "foo.bar[0][0]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.bar[0][0][0]",
+            "result": null
+         },
+         {
+            "expression": "foo.bar[0][0][0][0]",
+            "result": null
+         },
+         {
+            "expression": "foo[0][0]",
+            "result": null
+         }
+     ]
+},
+{
+    "given": {
+        "foo": [
+            {"bar": [{"kind": "basic"}, {"kind": "intermediate"}]},
+            {"bar": [{"kind": "advanced"}, {"kind": "expert"}]},
+            {"bar": "string"}
+        ]
+
+     },
+     "cases": [
+         {
+            "expression": "foo[*].bar[*].kind",
+            "result": [["basic", "intermediate"], ["advanced", "expert"]]
+         },
+         {
+            "expression": "foo[*].bar[0].kind",
+            "result": ["basic", "advanced"]
+         }
+     ]
+},
+{
+    "given": {
+        "foo": [
+            {"bar": {"kind": "basic"}},
+            {"bar": {"kind": "intermediate"}},
+            {"bar": {"kind": "advanced"}},
+            {"bar": {"kind": "expert"}},
+            {"bar": "string"}
+        ]
+     },
+     "cases": [
+         {
+            "expression": "foo[*].bar.kind",
+            "result": ["basic", "intermediate", "advanced", "expert"]
+         }
+     ]
+},
+{
+    "given": {
+        "foo": [{"bar": ["one", "two"]}, {"bar": ["three", "four"]}, {"bar": ["five"]}]
+     },
+     "cases": [
+         {
+            "expression": "foo[*].bar[0]",
+            "result": ["one", "three", "five"]
+         },
+         {
+            "expression": "foo[*].bar[1]",
+            "result": ["two", "four"]
+         },
+         {
+            "expression": "foo[*].bar[2]",
+            "result": []
+         }
+     ]
+},
+{
+    "given": {
+        "foo": [{"bar": []}, {"bar": []}, {"bar": []}]
+     },
+     "cases": [
+         {
+            "expression": "foo[*].bar[0]",
+            "result": []
+         }
+     ]
+},
+{
+    "given": {
+        "foo": [["one", "two"], ["three", "four"], ["five"]]
+     },
+     "cases": [
+         {
+            "expression": "foo[*][0]",
+            "result": ["one", "three", "five"]
+         },
+         {
+            "expression": "foo[*][1]",
+            "result": ["two", "four"]
+         }
+     ]
+},
+{
+    "given": {
+        "foo": [
+            [
+                ["one", "two"], ["three", "four"]
+            ], [
+                ["five", "six"], ["seven", "eight"]
+            ], [
+                ["nine"], ["ten"]
+            ]
+        ]
+     },
+     "cases": [
+         {
+            "expression": "foo[*][0]",
+            "result": [["one", "two"], ["five", "six"], ["nine"]]
+         },
+         {
+            "expression": "foo[*][1]",
+            "result": [["three", "four"], ["seven", "eight"], ["ten"]]
+         },
+         {
+            "expression": "foo[*][0][0]",
+            "result": ["one", "five", "nine"]
+         },
+         {
+            "expression": "foo[*][1][0]",
+            "result": ["three", "seven", "ten"]
+         },
+         {
+            "expression": "foo[*][0][1]",
+            "result": ["two", "six"]
+         },
+         {
+            "expression": "foo[*][1][1]",
+            "result": ["four", "eight"]
+         },
+         {
+            "expression": "foo[*][2]",
+            "result": []
+         },
+         {
+            "expression": "foo[*][2][2]",
+            "result": []
+         },
+         {
+            "expression": "bar[*]",
+            "result": null
+         },
+         {
+            "expression": "bar[*].baz[*]",
+            "result": null
+         }
+     ]
+},
+{
+    "given": {
+        "string": "string",
+        "hash": {"foo": "bar", "bar": "baz"},
+        "number": 23,
+        "nullvalue": null
+     },
+     "cases": [
+         {
+            "expression": "string[*]",
+            "result": null
+         },
+         {
+            "expression": "hash[*]",
+            "result": null
+         },
+         {
+            "expression": "number[*]",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[*]",
+            "result": null
+         },
+         {
+            "expression": "string[*].foo",
+            "result": null
+         },
+         {
+            "expression": "hash[*].foo",
+            "result": null
+         },
+         {
+            "expression": "number[*].foo",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[*].foo",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[*].foo[*].bar",
+            "result": null
+         }
+     ]
+},
+{
+    "given": {
+        "string": "string",
+        "hash": {"foo": "val", "bar": "val"},
+        "number": 23,
+        "array": [1, 2, 3],
+        "nullvalue": null
+     },
+     "cases": [
+         {
+            "expression": "string.*",
+            "result": null
+         },
+         {
+            "expression": "hash.*",
+            "result": ["val", "val"]
+         },
+         {
+            "expression": "number.*",
+            "result": null
+         },
+         {
+            "expression": "array.*",
+            "result": null
+         },
+         {
+            "expression": "nullvalue.*",
+            "result": null
+         }
+     ]
+},
+{
+    "given": {
+        "a": [0, 1, 2],
+        "b": [0, 1, 2]
+     },
+     "cases": [
+         {
+            "expression": "*[0]",
+            "result": [0, 0]
+         }
+     ]
+}
+]

+ 123 - 0
vendor/github.com/jmespath/go-jmespath/compliance_test.go

@@ -0,0 +1,123 @@
+package jmespath
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+type TestSuite struct {
+	Given     interface{}
+	TestCases []TestCase `json:"cases"`
+	Comment   string
+}
+type TestCase struct {
+	Comment    string
+	Expression string
+	Result     interface{}
+	Error      string
+}
+
+var whiteListed = []string{
+	"compliance/basic.json",
+	"compliance/current.json",
+	"compliance/escape.json",
+	"compliance/filters.json",
+	"compliance/functions.json",
+	"compliance/identifiers.json",
+	"compliance/indices.json",
+	"compliance/literal.json",
+	"compliance/multiselect.json",
+	"compliance/ormatch.json",
+	"compliance/pipe.json",
+	"compliance/slice.json",
+	"compliance/syntax.json",
+	"compliance/unicode.json",
+	"compliance/wildcard.json",
+	"compliance/boolean.json",
+}
+
+func allowed(path string) bool {
+	for _, el := range whiteListed {
+		if el == path {
+			return true
+		}
+	}
+	return false
+}
+
+func TestCompliance(t *testing.T) {
+	assert := assert.New(t)
+
+	var complianceFiles []string
+	err := filepath.Walk("compliance", func(path string, _ os.FileInfo, _ error) error {
+		//if strings.HasSuffix(path, ".json") {
+		if allowed(path) {
+			complianceFiles = append(complianceFiles, path)
+		}
+		return nil
+	})
+	if assert.Nil(err) {
+		for _, filename := range complianceFiles {
+			runComplianceTest(assert, filename)
+		}
+	}
+}
+
+func runComplianceTest(assert *assert.Assertions, filename string) {
+	var testSuites []TestSuite
+	data, err := ioutil.ReadFile(filename)
+	if assert.Nil(err) {
+		err := json.Unmarshal(data, &testSuites)
+		if assert.Nil(err) {
+			for _, testsuite := range testSuites {
+				runTestSuite(assert, testsuite, filename)
+			}
+		}
+	}
+}
+
+func runTestSuite(assert *assert.Assertions, testsuite TestSuite, filename string) {
+	for _, testcase := range testsuite.TestCases {
+		if testcase.Error != "" {
+			// This is a test case that verifies we error out properly.
+			runSyntaxTestCase(assert, testsuite.Given, testcase, filename)
+		} else {
+			runTestCase(assert, testsuite.Given, testcase, filename)
+		}
+	}
+}
+
+func runSyntaxTestCase(assert *assert.Assertions, given interface{}, testcase TestCase, filename string) {
+	// Anything with an .Error means that we expect that JMESPath should return
+	// an error when we try to evaluate the expression.
+	_, err := Search(testcase.Expression, given)
+	assert.NotNil(err, fmt.Sprintf("Expression: %s", testcase.Expression))
+}
+
+func runTestCase(assert *assert.Assertions, given interface{}, testcase TestCase, filename string) {
+	lexer := NewLexer()
+	var err error
+	_, err = lexer.tokenize(testcase.Expression)
+	if err != nil {
+		errMsg := fmt.Sprintf("(%s) Could not lex expression: %s -- %s", filename, testcase.Expression, err.Error())
+		assert.Fail(errMsg)
+		return
+	}
+	parser := NewParser()
+	_, err = parser.Parse(testcase.Expression)
+	if err != nil {
+		errMsg := fmt.Sprintf("(%s) Could not parse expression: %s -- %s", filename, testcase.Expression, err.Error())
+		assert.Fail(errMsg)
+		return
+	}
+	actual, err := Search(testcase.Expression, given)
+	if assert.Nil(err, fmt.Sprintf("Expression: %s", testcase.Expression)) {
+		assert.Equal(testcase.Result, actual, fmt.Sprintf("Expression: %s", testcase.Expression))
+	}
+}

+ 60 - 60
vendor/github.com/jmespath/go-jmespath/functions.go

@@ -124,197 +124,197 @@ type functionCaller struct {
 func newFunctionCaller() *functionCaller {
 	caller := &functionCaller{}
 	caller.functionTable = map[string]functionEntry{
-		"length": {
+		"length": functionEntry{
 			name: "length",
 			arguments: []argSpec{
-				{types: []jpType{jpString, jpArray, jpObject}},
+				argSpec{types: []jpType{jpString, jpArray, jpObject}},
 			},
 			handler: jpfLength,
 		},
-		"starts_with": {
+		"starts_with": functionEntry{
 			name: "starts_with",
 			arguments: []argSpec{
-				{types: []jpType{jpString}},
-				{types: []jpType{jpString}},
+				argSpec{types: []jpType{jpString}},
+				argSpec{types: []jpType{jpString}},
 			},
 			handler: jpfStartsWith,
 		},
-		"abs": {
+		"abs": functionEntry{
 			name: "abs",
 			arguments: []argSpec{
-				{types: []jpType{jpNumber}},
+				argSpec{types: []jpType{jpNumber}},
 			},
 			handler: jpfAbs,
 		},
-		"avg": {
+		"avg": functionEntry{
 			name: "avg",
 			arguments: []argSpec{
-				{types: []jpType{jpArrayNumber}},
+				argSpec{types: []jpType{jpArrayNumber}},
 			},
 			handler: jpfAvg,
 		},
-		"ceil": {
+		"ceil": functionEntry{
 			name: "ceil",
 			arguments: []argSpec{
-				{types: []jpType{jpNumber}},
+				argSpec{types: []jpType{jpNumber}},
 			},
 			handler: jpfCeil,
 		},
-		"contains": {
+		"contains": functionEntry{
 			name: "contains",
 			arguments: []argSpec{
-				{types: []jpType{jpArray, jpString}},
-				{types: []jpType{jpAny}},
+				argSpec{types: []jpType{jpArray, jpString}},
+				argSpec{types: []jpType{jpAny}},
 			},
 			handler: jpfContains,
 		},
-		"ends_with": {
+		"ends_with": functionEntry{
 			name: "ends_with",
 			arguments: []argSpec{
-				{types: []jpType{jpString}},
-				{types: []jpType{jpString}},
+				argSpec{types: []jpType{jpString}},
+				argSpec{types: []jpType{jpString}},
 			},
 			handler: jpfEndsWith,
 		},
-		"floor": {
+		"floor": functionEntry{
 			name: "floor",
 			arguments: []argSpec{
-				{types: []jpType{jpNumber}},
+				argSpec{types: []jpType{jpNumber}},
 			},
 			handler: jpfFloor,
 		},
-		"map": {
+		"map": functionEntry{
 			name: "amp",
 			arguments: []argSpec{
-				{types: []jpType{jpExpref}},
-				{types: []jpType{jpArray}},
+				argSpec{types: []jpType{jpExpref}},
+				argSpec{types: []jpType{jpArray}},
 			},
 			handler:   jpfMap,
 			hasExpRef: true,
 		},
-		"max": {
+		"max": functionEntry{
 			name: "max",
 			arguments: []argSpec{
-				{types: []jpType{jpArrayNumber, jpArrayString}},
+				argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
 			},
 			handler: jpfMax,
 		},
-		"merge": {
+		"merge": functionEntry{
 			name: "merge",
 			arguments: []argSpec{
-				{types: []jpType{jpObject}, variadic: true},
+				argSpec{types: []jpType{jpObject}, variadic: true},
 			},
 			handler: jpfMerge,
 		},
-		"max_by": {
+		"max_by": functionEntry{
 			name: "max_by",
 			arguments: []argSpec{
-				{types: []jpType{jpArray}},
-				{types: []jpType{jpExpref}},
+				argSpec{types: []jpType{jpArray}},
+				argSpec{types: []jpType{jpExpref}},
 			},
 			handler:   jpfMaxBy,
 			hasExpRef: true,
 		},
-		"sum": {
+		"sum": functionEntry{
 			name: "sum",
 			arguments: []argSpec{
-				{types: []jpType{jpArrayNumber}},
+				argSpec{types: []jpType{jpArrayNumber}},
 			},
 			handler: jpfSum,
 		},
-		"min": {
+		"min": functionEntry{
 			name: "min",
 			arguments: []argSpec{
-				{types: []jpType{jpArrayNumber, jpArrayString}},
+				argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
 			},
 			handler: jpfMin,
 		},
-		"min_by": {
+		"min_by": functionEntry{
 			name: "min_by",
 			arguments: []argSpec{
-				{types: []jpType{jpArray}},
-				{types: []jpType{jpExpref}},
+				argSpec{types: []jpType{jpArray}},
+				argSpec{types: []jpType{jpExpref}},
 			},
 			handler:   jpfMinBy,
 			hasExpRef: true,
 		},
-		"type": {
+		"type": functionEntry{
 			name: "type",
 			arguments: []argSpec{
-				{types: []jpType{jpAny}},
+				argSpec{types: []jpType{jpAny}},
 			},
 			handler: jpfType,
 		},
-		"keys": {
+		"keys": functionEntry{
 			name: "keys",
 			arguments: []argSpec{
-				{types: []jpType{jpObject}},
+				argSpec{types: []jpType{jpObject}},
 			},
 			handler: jpfKeys,
 		},
-		"values": {
+		"values": functionEntry{
 			name: "values",
 			arguments: []argSpec{
-				{types: []jpType{jpObject}},
+				argSpec{types: []jpType{jpObject}},
 			},
 			handler: jpfValues,
 		},
-		"sort": {
+		"sort": functionEntry{
 			name: "sort",
 			arguments: []argSpec{
-				{types: []jpType{jpArrayString, jpArrayNumber}},
+				argSpec{types: []jpType{jpArrayString, jpArrayNumber}},
 			},
 			handler: jpfSort,
 		},
-		"sort_by": {
+		"sort_by": functionEntry{
 			name: "sort_by",
 			arguments: []argSpec{
-				{types: []jpType{jpArray}},
-				{types: []jpType{jpExpref}},
+				argSpec{types: []jpType{jpArray}},
+				argSpec{types: []jpType{jpExpref}},
 			},
 			handler:   jpfSortBy,
 			hasExpRef: true,
 		},
-		"join": {
+		"join": functionEntry{
 			name: "join",
 			arguments: []argSpec{
-				{types: []jpType{jpString}},
-				{types: []jpType{jpArrayString}},
+				argSpec{types: []jpType{jpString}},
+				argSpec{types: []jpType{jpArrayString}},
 			},
 			handler: jpfJoin,
 		},
-		"reverse": {
+		"reverse": functionEntry{
 			name: "reverse",
 			arguments: []argSpec{
-				{types: []jpType{jpArray, jpString}},
+				argSpec{types: []jpType{jpArray, jpString}},
 			},
 			handler: jpfReverse,
 		},
-		"to_array": {
+		"to_array": functionEntry{
 			name: "to_array",
 			arguments: []argSpec{
-				{types: []jpType{jpAny}},
+				argSpec{types: []jpType{jpAny}},
 			},
 			handler: jpfToArray,
 		},
-		"to_string": {
+		"to_string": functionEntry{
 			name: "to_string",
 			arguments: []argSpec{
-				{types: []jpType{jpAny}},
+				argSpec{types: []jpType{jpAny}},
 			},
 			handler: jpfToString,
 		},
-		"to_number": {
+		"to_number": functionEntry{
 			name: "to_number",
 			arguments: []argSpec{
-				{types: []jpType{jpAny}},
+				argSpec{types: []jpType{jpAny}},
 			},
 			handler: jpfToNumber,
 		},
-		"not_null": {
+		"not_null": functionEntry{
 			name: "not_null",
 			arguments: []argSpec{
-				{types: []jpType{jpAny}, variadic: true},
+				argSpec{types: []jpType{jpAny}, variadic: true},
 			},
 			handler: jpfNotNull,
 		},

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-1

@@ -0,0 +1 @@
+foo

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-10

@@ -0,0 +1 @@
+foo.bar

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-100

@@ -0,0 +1 @@
+ends_with(str, 'SStr')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-101

@@ -0,0 +1 @@
+ends_with(str, 'foo')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-102

@@ -0,0 +1 @@
+floor(`1.2`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-103

@@ -0,0 +1 @@
+floor(decimals[0])

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-104

@@ -0,0 +1 @@
+floor(foo)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-105

@@ -0,0 +1 @@
+length('abc')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-106

@@ -0,0 +1 @@
+length('')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-107

@@ -0,0 +1 @@
+length(@)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-108

@@ -0,0 +1 @@
+length(strings[0])

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-109

@@ -0,0 +1 @@
+length(str)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-110

@@ -0,0 +1 @@
+length(array)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-112

@@ -0,0 +1 @@
+length(strings[0])

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-115

@@ -0,0 +1 @@
+max(strings)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-118

@@ -0,0 +1 @@
+merge(`{}`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-119

@@ -0,0 +1 @@
+merge(`{}`, `{}`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-12

@@ -0,0 +1 @@
+two

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-120

@@ -0,0 +1 @@
+merge(`{"a": 1}`, `{"b": 2}`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-121

@@ -0,0 +1 @@
+merge(`{"a": 1}`, `{"a": 2}`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-122

@@ -0,0 +1 @@
+merge(`{"a": 1, "b": 2}`, `{"a": 2, "c": 3}`, `{"d": 4}`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-123

@@ -0,0 +1 @@
+min(numbers)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-126

@@ -0,0 +1 @@
+min(decimals)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-128

@@ -0,0 +1 @@
+type('abc')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-129

@@ -0,0 +1 @@
+type(`1.0`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-13

@@ -0,0 +1 @@
+three

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-130

@@ -0,0 +1 @@
+type(`2`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-131

@@ -0,0 +1 @@
+type(`true`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-132

@@ -0,0 +1 @@
+type(`false`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-133

@@ -0,0 +1 @@
+type(`null`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-134

@@ -0,0 +1 @@
+type(`[0]`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-135

@@ -0,0 +1 @@
+type(`{"a": "b"}`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-136

@@ -0,0 +1 @@
+type(@)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-137

@@ -0,0 +1 @@
+keys(objects)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-138

@@ -0,0 +1 @@
+values(objects)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-139

@@ -0,0 +1 @@
+keys(empty_hash)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-14

@@ -0,0 +1 @@
+one.two

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-140

@@ -0,0 +1 @@
+join(', ', strings)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-141

@@ -0,0 +1 @@
+join(', ', strings)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-142

@@ -0,0 +1 @@
+join(',', `["a", "b"]`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-143

@@ -0,0 +1 @@
+join('|', strings)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-144

@@ -0,0 +1 @@
+join('|', decimals[].to_string(@))

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-145

@@ -0,0 +1 @@
+join('|', empty_list)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-146

@@ -0,0 +1 @@
+reverse(numbers)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-147

@@ -0,0 +1 @@
+reverse(array)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-148

@@ -0,0 +1 @@
+reverse(`[]`)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-149

@@ -0,0 +1 @@
+reverse('')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-15

@@ -0,0 +1 @@
+foo."1"

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-150

@@ -0,0 +1 @@
+reverse('hello world')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-151

@@ -0,0 +1 @@
+starts_with(str, 'S')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-152

@@ -0,0 +1 @@
+starts_with(str, 'St')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-153

@@ -0,0 +1 @@
+starts_with(str, 'Str')

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-155

@@ -0,0 +1 @@
+sum(numbers)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-156

@@ -0,0 +1 @@
+sum(decimals)

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-157

@@ -0,0 +1 @@
+sum(array[].to_number(@))

+ 1 - 0
vendor/github.com/jmespath/go-jmespath/fuzz/corpus/expr-158

@@ -0,0 +1 @@
+sum(`[]`)

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff