diff --git a/vendor/gotest.tools/assert/cmp/compare.go b/vendor/gotest.tools/assert/cmp/compare.go
new file mode 100644
index 0000000..cf48d88
--- /dev/null
+++ b/vendor/gotest.tools/assert/cmp/compare.go
@@ -0,0 +1,356 @@
+/*Package cmp provides Comparisons for Assert and Check*/
+package cmp // import "gotest.tools/assert/cmp"
+
+import (
+	"fmt"
+	"reflect"
+	"regexp"
+	"strings"
+
+	"github.com/google/go-cmp/cmp"
+	"gotest.tools/internal/format"
+)
+
+// Comparison is a function which compares values and returns ResultSuccess if
+// the actual value matches the expected value. If the values do not match the
+// Result will contain a message about why it failed.
+type Comparison func() Result
+
+// DeepEqual compares two values using google/go-cmp (http://bit.do/go-cmp)
+// and succeeds if the values are equal.
+//
+// The comparison can be customized using comparison Options.
+// Package https://godoc.org/gotest.tools/assert/opt provides some additional
+// commonly used Options.
+func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison {
+	return func() (result Result) {
+		defer func() {
+			if panicmsg, handled := handleCmpPanic(recover()); handled {
+				result = ResultFailure(panicmsg)
+			}
+		}()
+		diff := cmp.Diff(x, y, opts...)
+		if diff == "" {
+			return ResultSuccess
+		}
+		return multiLineDiffResult(diff)
+	}
+}
+
+func handleCmpPanic(r interface{}) (string, bool) {
+	if r == nil {
+		return "", false
+	}
+	panicmsg, ok := r.(string)
+	if !ok {
+		panic(r)
+	}
+	switch {
+	case strings.HasPrefix(panicmsg, "cannot handle unexported field"):
+		return panicmsg, true
+	}
+	panic(r)
+}
+
+func toResult(success bool, msg string) Result {
+	if success {
+		return ResultSuccess
+	}
+	return ResultFailure(msg)
+}
+
+// RegexOrPattern may be either a *regexp.Regexp or a string that is a valid
+// regexp pattern.
+type RegexOrPattern interface{}
+
+// Regexp succeeds if value v matches regular expression re.
+//
+// Example:
+//   assert.Assert(t, cmp.Regexp("^[0-9a-f]{32}$", str))
+//   r := regexp.MustCompile("^[0-9a-f]{32}$")
+//   assert.Assert(t, cmp.Regexp(r, str))
+func Regexp(re RegexOrPattern, v string) Comparison {
+	match := func(re *regexp.Regexp) Result {
+		return toResult(
+			re.MatchString(v),
+			fmt.Sprintf("value %q does not match regexp %q", v, re.String()))
+	}
+
+	return func() Result {
+		switch regex := re.(type) {
+		case *regexp.Regexp:
+			return match(regex)
+		case string:
+			re, err := regexp.Compile(regex)
+			if err != nil {
+				return ResultFailure(err.Error())
+			}
+			return match(re)
+		default:
+			return ResultFailure(fmt.Sprintf("invalid type %T for regex pattern", regex))
+		}
+	}
+}
+
+// Equal succeeds if x == y. See assert.Equal for full documentation.
+func Equal(x, y interface{}) Comparison {
+	return func() Result {
+		switch {
+		case x == y:
+			return ResultSuccess
+		case isMultiLineStringCompare(x, y):
+			diff := format.UnifiedDiff(format.DiffConfig{A: x.(string), B: y.(string)})
+			return multiLineDiffResult(diff)
+		}
+		return ResultFailureTemplate(`
+			{{- .Data.x}} (
+				{{- with callArg 0 }}{{ formatNode . }} {{end -}}
+				{{- printf "%T" .Data.x -}}
+			) != {{ .Data.y}} (
+				{{- with callArg 1 }}{{ formatNode . }} {{end -}}
+				{{- printf "%T" .Data.y -}}
+			)`,
+			map[string]interface{}{"x": x, "y": y})
+	}
+}
+
+func isMultiLineStringCompare(x, y interface{}) bool {
+	strX, ok := x.(string)
+	if !ok {
+		return false
+	}
+	strY, ok := y.(string)
+	if !ok {
+		return false
+	}
+	return strings.Contains(strX, "\n") || strings.Contains(strY, "\n")
+}
+
+func multiLineDiffResult(diff string) Result {
+	return ResultFailureTemplate(`
+--- {{ with callArg 0 }}{{ formatNode . }}{{else}}←{{end}}
++++ {{ with callArg 1 }}{{ formatNode . }}{{else}}→{{end}}
+{{ .Data.diff }}`,
+		map[string]interface{}{"diff": diff})
+}
+
+// Len succeeds if the sequence has the expected length.
+func Len(seq interface{}, expected int) Comparison {
+	return func() (result Result) {
+		defer func() {
+			if e := recover(); e != nil {
+				result = ResultFailure(fmt.Sprintf("type %T does not have a length", seq))
+			}
+		}()
+		value := reflect.ValueOf(seq)
+		length := value.Len()
+		if length == expected {
+			return ResultSuccess
+		}
+		msg := fmt.Sprintf("expected %s (length %d) to have length %d", seq, length, expected)
+		return ResultFailure(msg)
+	}
+}
+
+// Contains succeeds if item is in collection. Collection may be a string, map,
+// slice, or array.
+//
+// If collection is a string, item must also be a string, and is compared using
+// strings.Contains().
+// If collection is a Map, contains will succeed if item is a key in the map.
+// If collection is a slice or array, item is compared to each item in the
+// sequence using reflect.DeepEqual().
+func Contains(collection interface{}, item interface{}) Comparison {
+	return func() Result {
+		colValue := reflect.ValueOf(collection)
+		if !colValue.IsValid() {
+			return ResultFailure(fmt.Sprintf("nil does not contain items"))
+		}
+		msg := fmt.Sprintf("%v does not contain %v", collection, item)
+
+		itemValue := reflect.ValueOf(item)
+		switch colValue.Type().Kind() {
+		case reflect.String:
+			if itemValue.Type().Kind() != reflect.String {
+				return ResultFailure("string may only contain strings")
+			}
+			return toResult(
+				strings.Contains(colValue.String(), itemValue.String()),
+				fmt.Sprintf("string %q does not contain %q", collection, item))
+
+		case reflect.Map:
+			if itemValue.Type() != colValue.Type().Key() {
+				return ResultFailure(fmt.Sprintf(
+					"%v can not contain a %v key", colValue.Type(), itemValue.Type()))
+			}
+			return toResult(colValue.MapIndex(itemValue).IsValid(), msg)
+
+		case reflect.Slice, reflect.Array:
+			for i := 0; i < colValue.Len(); i++ {
+				if reflect.DeepEqual(colValue.Index(i).Interface(), item) {
+					return ResultSuccess
+				}
+			}
+			return ResultFailure(msg)
+		default:
+			return ResultFailure(fmt.Sprintf("type %T does not contain items", collection))
+		}
+	}
+}
+
+// Panics succeeds if f() panics.
+func Panics(f func()) Comparison {
+	return func() (result Result) {
+		defer func() {
+			if err := recover(); err != nil {
+				result = ResultSuccess
+			}
+		}()
+		f()
+		return ResultFailure("did not panic")
+	}
+}
+
+// Error succeeds if err is a non-nil error, and the error message equals the
+// expected message.
+func Error(err error, message string) Comparison {
+	return func() Result {
+		switch {
+		case err == nil:
+			return ResultFailure("expected an error, got nil")
+		case err.Error() != message:
+			return ResultFailure(fmt.Sprintf(
+				"expected error %q, got %s", message, formatErrorMessage(err)))
+		}
+		return ResultSuccess
+	}
+}
+
+// ErrorContains succeeds if err is a non-nil error, and the error message contains
+// the expected substring.
+func ErrorContains(err error, substring string) Comparison {
+	return func() Result {
+		switch {
+		case err == nil:
+			return ResultFailure("expected an error, got nil")
+		case !strings.Contains(err.Error(), substring):
+			return ResultFailure(fmt.Sprintf(
+				"expected error to contain %q, got %s", substring, formatErrorMessage(err)))
+		}
+		return ResultSuccess
+	}
+}
+
+func formatErrorMessage(err error) string {
+	if _, ok := err.(interface {
+		Cause() error
+	}); ok {
+		return fmt.Sprintf("%q\n%+v", err, err)
+	}
+	// This error was not wrapped with github.com/pkg/errors
+	return fmt.Sprintf("%q", err)
+}
+
+// Nil succeeds if obj is a nil interface, pointer, or function.
+//
+// Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices,
+// maps, and channels.
+func Nil(obj interface{}) Comparison {
+	msgFunc := func(value reflect.Value) string {
+		return fmt.Sprintf("%v (type %s) is not nil", reflect.Indirect(value), value.Type())
+	}
+	return isNil(obj, msgFunc)
+}
+
+func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison {
+	return func() Result {
+		if obj == nil {
+			return ResultSuccess
+		}
+		value := reflect.ValueOf(obj)
+		kind := value.Type().Kind()
+		if kind >= reflect.Chan && kind <= reflect.Slice {
+			if value.IsNil() {
+				return ResultSuccess
+			}
+			return ResultFailure(msgFunc(value))
+		}
+
+		return ResultFailure(fmt.Sprintf("%v (type %s) can not be nil", value, value.Type()))
+	}
+}
+
+// ErrorType succeeds if err is not nil and is of the expected type.
+//
+// Expected can be one of:
+// a func(error) bool which returns true if the error is the expected type,
+// an instance of (or a pointer to) a struct of the expected type,
+// a pointer to an interface the error is expected to implement,
+// a reflect.Type of the expected struct or interface.
+func ErrorType(err error, expected interface{}) Comparison {
+	return func() Result {
+		switch expectedType := expected.(type) {
+		case func(error) bool:
+			return cmpErrorTypeFunc(err, expectedType)
+		case reflect.Type:
+			if expectedType.Kind() == reflect.Interface {
+				return cmpErrorTypeImplementsType(err, expectedType)
+			}
+			return cmpErrorTypeEqualType(err, expectedType)
+		case nil:
+			return ResultFailure(fmt.Sprintf("invalid type for expected: nil"))
+		}
+
+		expectedType := reflect.TypeOf(expected)
+		switch {
+		case expectedType.Kind() == reflect.Struct, isPtrToStruct(expectedType):
+			return cmpErrorTypeEqualType(err, expectedType)
+		case isPtrToInterface(expectedType):
+			return cmpErrorTypeImplementsType(err, expectedType.Elem())
+		}
+		return ResultFailure(fmt.Sprintf("invalid type for expected: %T", expected))
+	}
+}
+
+func cmpErrorTypeFunc(err error, f func(error) bool) Result {
+	if f(err) {
+		return ResultSuccess
+	}
+	actual := "nil"
+	if err != nil {
+		actual = fmt.Sprintf("%s (%T)", err, err)
+	}
+	return ResultFailureTemplate(`error is {{ .Data.actual }}
+		{{- with callArg 1 }}, not {{ formatNode . }}{{end -}}`,
+		map[string]interface{}{"actual": actual})
+}
+
+func cmpErrorTypeEqualType(err error, expectedType reflect.Type) Result {
+	if err == nil {
+		return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType))
+	}
+	errValue := reflect.ValueOf(err)
+	if errValue.Type() == expectedType {
+		return ResultSuccess
+	}
+	return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType))
+}
+
+func cmpErrorTypeImplementsType(err error, expectedType reflect.Type) Result {
+	if err == nil {
+		return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType))
+	}
+	errValue := reflect.ValueOf(err)
+	if errValue.Type().Implements(expectedType) {
+		return ResultSuccess
+	}
+	return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType))
+}
+
+func isPtrToInterface(typ reflect.Type) bool {
+	return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface
+}
+
+func isPtrToStruct(typ reflect.Type) bool {
+	return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct
+}
