1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-09 09:26:54 +00:00
kyverno/vendor/gotest.tools/assert/cmp/compare_test.go

584 lines
13 KiB
Go

package cmp
import (
"fmt"
"go/ast"
"io"
"reflect"
"regexp"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/pkg/errors"
)
func TestDeepEqual(t *testing.T) {
actual := DeepEqual([]string{"a", "b"}, []string{"b", "a"})()
expected := `
--- result
+++ exp
{[]string}[0]:
-: "a"
+: "b"
{[]string}[1]:
-: "b"
+: "a"
`
args := []ast.Expr{&ast.Ident{Name: "result"}, &ast.Ident{Name: "exp"}}
assertFailureTemplate(t, actual, args, expected)
actual = DeepEqual([]string{"a"}, []string{"a"})()
assertSuccess(t, actual)
}
type Stub struct {
unx int
}
func TestDeepEqualeWithUnexported(t *testing.T) {
result := DeepEqual(Stub{}, Stub{unx: 1})()
assertFailure(t, result, `cannot handle unexported field: {cmp.Stub}.unx
consider using AllowUnexported or cmpopts.IgnoreUnexported`)
}
func TestRegexp(t *testing.T) {
var testcases = []struct {
name string
regex interface{}
value string
match bool
expErr string
}{
{
name: "pattern string match",
regex: "^[0-9]+$",
value: "12123423456",
match: true,
},
{
name: "simple pattern string no match",
regex: "bob",
value: "Probably",
expErr: `value "Probably" does not match regexp "bob"`,
},
{
name: "pattern string no match",
regex: "^1",
value: "2123423456",
expErr: `value "2123423456" does not match regexp "^1"`,
},
{
name: "regexp match",
regex: regexp.MustCompile("^d[0-9a-f]{8}$"),
value: "d1632beef",
match: true,
},
{
name: "invalid regexp",
regex: "^1(",
value: "2",
expErr: "error parsing regexp: missing closing ): `^1(`",
},
{
name: "invalid type",
regex: struct{}{},
value: "some string",
expErr: "invalid type struct {} for regex pattern",
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
res := Regexp(tc.regex, tc.value)()
if tc.match {
assertSuccess(t, res)
} else {
assertFailure(t, res, tc.expErr)
}
})
}
}
func TestLen(t *testing.T) {
var testcases = []struct {
seq interface{}
length int
expectedSuccess bool
expectedMessage string
}{
{
seq: []string{"A", "b", "c"},
length: 3,
expectedSuccess: true,
},
{
seq: []string{"A", "b", "c"},
length: 2,
expectedMessage: "expected [A b c] (length 3) to have length 2",
},
{
seq: map[string]int{"a": 1, "b": 2},
length: 2,
expectedSuccess: true,
},
{
seq: [3]string{"a", "b", "c"},
length: 3,
expectedSuccess: true,
},
{
seq: "abcd",
length: 4,
expectedSuccess: true,
},
{
seq: "abcd",
length: 3,
expectedMessage: "expected abcd (length 4) to have length 3",
},
}
for _, testcase := range testcases {
t.Run(fmt.Sprintf("%v len=%d", testcase.seq, testcase.length), func(t *testing.T) {
result := Len(testcase.seq, testcase.length)()
if testcase.expectedSuccess {
assertSuccess(t, result)
} else {
assertFailure(t, result, testcase.expectedMessage)
}
})
}
}
func TestPanics(t *testing.T) {
panicker := func() {
panic("AHHHHHHHHHHH")
}
result := Panics(panicker)()
assertSuccess(t, result)
result = Panics(func() {})()
assertFailure(t, result, "did not panic")
}
type innerstub struct {
num int
}
type stub struct {
stub innerstub
num int
}
func TestDeepEqualEquivalenceToReflectDeepEqual(t *testing.T) {
var testcases = []struct {
left interface{}
right interface{}
}{
{nil, nil},
{7, 7},
{false, false},
{stub{innerstub{1}, 2}, stub{innerstub{1}, 2}},
{[]int{1, 2, 3}, []int{1, 2, 3}},
{[]byte(nil), []byte(nil)},
{nil, []byte(nil)},
{1, uint64(1)},
{7, "7"},
}
for _, testcase := range testcases {
expected := reflect.DeepEqual(testcase.left, testcase.right)
res := DeepEqual(testcase.left, testcase.right, cmpStub)()
if res.Success() != expected {
msg := res.(StringResult).FailureMessage()
t.Errorf("deepEqual(%v, %v) did not return %v (message %s)",
testcase.left, testcase.right, expected, msg)
}
}
}
var cmpStub = cmp.AllowUnexported(stub{}, innerstub{})
func TestContains(t *testing.T) {
var testcases = []struct {
seq interface{}
item interface{}
expected bool
expectedMsg string
}{
{
seq: error(nil),
item: 0,
expectedMsg: "nil does not contain items",
},
{
seq: "abcdef",
item: "cde",
expected: true,
},
{
seq: "abcdef",
item: "foo",
expectedMsg: `string "abcdef" does not contain "foo"`,
},
{
seq: "abcdef",
item: 3,
expectedMsg: `string may only contain strings`,
},
{
seq: map[rune]int{'a': 1, 'b': 2},
item: 'b',
expected: true,
},
{
seq: map[rune]int{'a': 1},
item: 'c',
expectedMsg: "map[97:1] does not contain 99",
},
{
seq: map[int]int{'a': 1, 'b': 2},
item: 'b',
expectedMsg: "map[int]int can not contain a int32 key",
},
{
seq: []interface{}{"a", 1, 'a', 1.0, true},
item: 'a',
expected: true,
},
{
seq: []interface{}{"a", 1, 'a', 1.0, true},
item: 3,
expectedMsg: "[a 1 97 1 true] does not contain 3",
},
{
seq: [3]byte{99, 10, 100},
item: byte(99),
expected: true,
},
{
seq: [3]byte{99, 10, 100},
item: byte(98),
expectedMsg: "[99 10 100] does not contain 98",
},
}
for _, testcase := range testcases {
name := fmt.Sprintf("%v in %v", testcase.item, testcase.seq)
t.Run(name, func(t *testing.T) {
result := Contains(testcase.seq, testcase.item)()
if testcase.expected {
assertSuccess(t, result)
} else {
assertFailure(t, result, testcase.expectedMsg)
}
})
}
}
func TestEqualMultiLine(t *testing.T) {
result := `abcd
1234
aaaa
bbbb`
exp := `abcd
1111
aaaa
bbbb`
expected := `
--- result
+++ exp
@@ -1,4 +1,4 @@
abcd
-1234
+1111
aaaa
bbbb
`
args := []ast.Expr{&ast.Ident{Name: "result"}, &ast.Ident{Name: "exp"}}
res := Equal(result, exp)()
assertFailureTemplate(t, res, args, expected)
}
func TestError(t *testing.T) {
result := Error(nil, "the error message")()
assertFailure(t, result, "expected an error, got nil")
// A Wrapped error also includes the stack
result = Error(errors.Wrap(errors.New("other"), "wrapped"), "the error message")()
assertFailureHasPrefix(t, result,
`expected error "the error message", got "wrapped: other"
other
gotest.tools/assert/cmp.TestError`)
msg := "the message"
result = Error(errors.New(msg), msg)()
assertSuccess(t, result)
}
func TestErrorContains(t *testing.T) {
result := ErrorContains(nil, "the error message")()
assertFailure(t, result, "expected an error, got nil")
result = ErrorContains(errors.New("other"), "the error")()
assertFailureHasPrefix(t, result,
`expected error to contain "the error", got "other"`)
msg := "the full message"
result = ErrorContains(errors.New(msg), "full")()
assertSuccess(t, result)
}
func TestNil(t *testing.T) {
result := Nil(nil)()
assertSuccess(t, result)
var s *string
result = Nil(s)()
assertSuccess(t, result)
var closer io.Closer
result = Nil(closer)()
assertSuccess(t, result)
result = Nil("wrong")()
assertFailure(t, result, "wrong (type string) can not be nil")
notnil := "notnil"
result = Nil(&notnil)()
assertFailure(t, result, "notnil (type *string) is not nil")
result = Nil([]string{"a"})()
assertFailure(t, result, "[a] (type []string) is not nil")
}
type testingT interface {
Errorf(msg string, args ...interface{})
}
type helperT interface {
Helper()
}
func assertSuccess(t testingT, res Result) {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
if !res.Success() {
msg := res.(StringResult).FailureMessage()
t.Errorf("expected success, but got failure with message %q", msg)
}
}
func assertFailure(t testingT, res Result, expected string) {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
if res.Success() {
t.Errorf("expected failure")
}
message := res.(StringResult).FailureMessage()
if message != expected {
t.Errorf("expected \n%q\ngot\n%q\n", expected, message)
}
}
func assertFailureHasPrefix(t testingT, res Result, prefix string) {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
if res.Success() {
t.Errorf("expected failure")
}
message := res.(StringResult).FailureMessage()
if !strings.HasPrefix(message, prefix) {
t.Errorf("expected \n%v\nto start with\n%v\n", message, prefix)
}
}
// nolint: unparam
func assertFailureTemplate(t testingT, res Result, args []ast.Expr, expected string) {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
if res.Success() {
t.Errorf("expected failure")
}
message := res.(templatedResult).FailureMessage(args)
if message != expected {
t.Errorf("expected \n%q\ngot\n%q\n", expected, message)
}
}
type stubError struct{}
func (s stubError) Error() string {
return "stub error"
}
func isErrorOfTypeStub(err error) bool {
return reflect.TypeOf(err) == reflect.TypeOf(stubError{})
}
type notStubError struct{}
func (s notStubError) Error() string {
return "not stub error"
}
func isErrorOfTypeNotStub(err error) bool {
return reflect.TypeOf(err) == reflect.TypeOf(notStubError{})
}
type specialStubIface interface {
Special()
}
type stubPtrError struct{}
func (s *stubPtrError) Error() string {
return "stub ptr error"
}
func TestErrorTypeWithNil(t *testing.T) {
var testcases = []struct {
name string
expType interface{}
expected string
}{
{
name: "with struct",
expType: stubError{},
expected: "error is nil, not cmp.stubError",
},
{
name: "with pointer to struct",
expType: &stubPtrError{},
expected: "error is nil, not *cmp.stubPtrError",
},
{
name: "with interface",
expType: (*specialStubIface)(nil),
expected: "error is nil, not cmp.specialStubIface",
},
{
name: "with reflect.Type",
expType: reflect.TypeOf(stubError{}),
expected: "error is nil, not cmp.stubError",
},
}
for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
result := ErrorType(nil, testcase.expType)()
assertFailure(t, result, testcase.expected)
})
}
}
func TestErrorTypeSuccess(t *testing.T) {
var testcases = []struct {
name string
expType interface{}
err error
}{
{
name: "with function",
expType: isErrorOfTypeStub,
err: stubError{},
},
{
name: "with struct",
expType: stubError{},
err: stubError{},
},
{
name: "with pointer to struct",
expType: &stubPtrError{},
err: &stubPtrError{},
},
{
name: "with interface",
expType: (*error)(nil),
err: stubError{},
},
{
name: "with reflect.Type struct",
expType: reflect.TypeOf(stubError{}),
err: stubError{},
},
{
name: "with reflect.Type interface",
expType: reflect.TypeOf((*error)(nil)).Elem(),
err: stubError{},
},
}
for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
result := ErrorType(testcase.err, testcase.expType)()
assertSuccess(t, result)
})
}
}
func TestErrorTypeFailure(t *testing.T) {
var testcases = []struct {
name string
expType interface{}
expected string
}{
{
name: "with struct",
expType: notStubError{},
expected: "error is stub error (cmp.stubError), not cmp.notStubError",
},
{
name: "with pointer to struct",
expType: &stubPtrError{},
expected: "error is stub error (cmp.stubError), not *cmp.stubPtrError",
},
{
name: "with interface",
expType: (*specialStubIface)(nil),
expected: "error is stub error (cmp.stubError), not cmp.specialStubIface",
},
{
name: "with reflect.Type struct",
expType: reflect.TypeOf(notStubError{}),
expected: "error is stub error (cmp.stubError), not cmp.notStubError",
},
{
name: "with reflect.Type interface",
expType: reflect.TypeOf((*specialStubIface)(nil)).Elem(),
expected: "error is stub error (cmp.stubError), not cmp.specialStubIface",
},
}
for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
result := ErrorType(stubError{}, testcase.expType)()
assertFailure(t, result, testcase.expected)
})
}
}
func TestErrorTypeInvalid(t *testing.T) {
result := ErrorType(stubError{}, nil)()
assertFailure(t, result, "invalid type for expected: nil")
result = ErrorType(stubError{}, "my type!")()
assertFailure(t, result, "invalid type for expected: string")
}
func TestErrorTypeWithFunc(t *testing.T) {
result := ErrorType(nil, isErrorOfTypeStub)()
assertFailureTemplate(t, result,
[]ast.Expr{nil, &ast.Ident{Name: "isErrorOfTypeStub"}},
"error is nil, not isErrorOfTypeStub")
result = ErrorType(stubError{}, isErrorOfTypeNotStub)()
assertFailureTemplate(t, result,
[]ast.Expr{nil, &ast.Ident{Name: "isErrorOfTypeNotStub"}},
"error is stub error (cmp.stubError), not isErrorOfTypeNotStub")
}