Files
wazero/internal/testing/require/require_test.go
Crypt Keeper 1e383881ed Removes testify dependency (#462)
This implements our own assertion library so that we can remove the
testify dependency. I've changed a lot of call sites so that we only
have to maintain a minimal amount of assertions.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-04-14 16:37:43 +08:00

672 lines
15 KiB
Go

package require
import (
"errors"
"fmt"
"io"
"testing"
)
func TestCapturePanic(t *testing.T) {
tests := []struct {
name string
panics func()
expectedErr string
}{
{
name: "doesn't panic",
panics: func() {},
expectedErr: "",
},
{
name: "panics with error",
panics: func() { panic(errors.New("error")) },
expectedErr: "error",
},
{
name: "panics with string",
panics: func() { panic("crash") },
expectedErr: "crash",
},
{
name: "panics with object",
panics: func() { panic(struct{}{}) },
expectedErr: "{}",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
captured := CapturePanic(tc.panics)
if tc.expectedErr == "" {
if captured != nil {
t.Fatalf("expected no error, but found %v", captured)
}
} else {
if captured.Error() != tc.expectedErr {
t.Fatalf("expected %s, but found %s", tc.expectedErr, captured.Error())
}
}
})
}
}
func TestFail(t *testing.T) {
tests := []struct {
name string
formatWithArgs []interface{}
expectedLog string
}{
{
name: "message no formatWithArgs",
expectedLog: "failed",
},
{
name: "message formatWithArgs =: string",
formatWithArgs: []interface{}{"because"},
expectedLog: "failed: because",
},
{
name: "message formatWithArgs = [number]",
formatWithArgs: []interface{}{1},
expectedLog: "failed: 1",
},
{
name: "message formatWithArgs = [struct]",
formatWithArgs: []interface{}{struct{}{}},
expectedLog: "failed: {}",
},
{
name: "message formatWithArgs = [string, string]",
formatWithArgs: []interface{}{"because", "this"},
expectedLog: "failed: because this",
},
{
name: "message formatWithArgs = [format, string]",
formatWithArgs: []interface{}{"because %s", "this"},
expectedLog: "failed: because this",
},
{
name: "message formatWithArgs = [format, struct]",
formatWithArgs: []interface{}{"because %s", struct{}{}},
expectedLog: "failed: because {}",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
m := &mockT{t: t}
fail(m, "failed", "", tc.formatWithArgs...)
m.require(tc.expectedLog)
})
}
}
type testStruct struct {
name string
}
func TestRequire(t *testing.T) {
zero := uint64(0)
struct1 := &testStruct{"hello"}
struct2 := &testStruct{"hello"}
tests := []struct {
name string
require func(TestingT)
expectedLog string
}{
{
name: "Contains passes on contains",
require: func(t TestingT) {
Contains(t, "hello cat", "cat")
},
},
{
name: "Contains fails on empty",
require: func(t TestingT) {
Contains(t, "", "dog")
},
expectedLog: `expected "" to contain "dog"`,
},
{
name: "Contains fails on not contains",
require: func(t TestingT) {
Contains(t, "hello cat", "dog")
},
expectedLog: `expected "hello cat" to contain "dog"`,
},
{
name: "Contains fails on not contains with format",
require: func(t TestingT) {
Contains(t, "hello cat", "dog", "pay me %d", 5)
},
expectedLog: `expected "hello cat" to contain "dog": pay me 5`,
},
{
name: "Equal passes on equal: string",
require: func(t TestingT) {
Equal(t, "wazero", "wazero")
},
},
{
name: "Equal passes on equal: []byte",
require: func(t TestingT) {
Equal(t, []byte{1, 2, 3, 4}, []byte{1, 2, 3, 4})
},
},
{
name: "Equal passes on equal: struct",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, &testStruct{name: "takeshi"})
},
},
{
name: "Equal fails on nil: string",
require: func(t TestingT) {
Equal(t, "wazero", nil)
},
expectedLog: `expected "wazero", but was nil`,
},
{
name: "Equal fails on nil: []byte",
require: func(t TestingT) {
Equal(t, []byte{1, 2, 3, 4}, nil)
},
expectedLog: `expected []byte{0x1, 0x2, 0x3, 0x4}, but was nil`,
},
{
name: "Equal fails on nil: struct",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, nil)
},
expectedLog: `expected &require.testStruct{name:"takeshi"}, but was nil`,
},
{
name: "Equal fails on not same type: string",
require: func(t TestingT) {
Equal(t, "wazero", uint32(1))
},
expectedLog: `expected "wazero", but was uint32(1)`,
},
{
name: "Equal fails on not same type: []byte",
require: func(t TestingT) {
Equal(t, []byte{1, 2, 3, 4}, "wazero")
},
expectedLog: `expected []uint8([1 2 3 4]), but was string(wazero)`,
},
{
name: "Equal fails on not same type: struct",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, "wazero")
},
expectedLog: `expected *require.testStruct(&{takeshi}), but was string(wazero)`,
},
{
name: "Equal fails on not equal: string",
require: func(t TestingT) {
Equal(t, "wazero", "walero")
},
expectedLog: `expected "wazero", but was "walero"`,
},
{
name: "Equal fails on not equal: uint64", // ensure we don't use multi-line output!
require: func(t TestingT) {
Equal(t, uint64(12), uint64(13))
},
expectedLog: `expected 12, but was 13`,
},
{
name: "Equal fails on not equal: []byte",
require: func(t TestingT) {
Equal(t, []byte{1, 2, 3, 4}, []byte{1, 2, 4})
},
expectedLog: `unexpected value
expected:
[]byte{0x1, 0x2, 0x3, 0x4}
was:
[]byte{0x1, 0x2, 0x4}
`,
},
{
name: "Equal fails on not equal: struct",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, &testStruct{name: "adrian"})
},
expectedLog: `unexpected value
expected:
&require.testStruct{name:"takeshi"}
was:
&require.testStruct{name:"adrian"}
`,
},
{
name: "Equal fails on not equal: struct with format",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, &testStruct{name: "adrian"}, "pay me %d", 5)
},
expectedLog: `unexpected value: pay me 5
expected:
&require.testStruct{name:"takeshi"}
was:
&require.testStruct{name:"adrian"}
`,
},
{
name: "EqualError passes on equal",
require: func(t TestingT) {
EqualError(t, io.EOF, io.EOF.Error())
},
},
{
name: "EqualError fails on nil",
require: func(t TestingT) {
EqualError(t, nil, "crash")
},
expectedLog: "expected an error, but was nil",
},
{
name: "EqualError fails on not equal",
require: func(t TestingT) {
EqualError(t, io.EOF, "crash")
},
expectedLog: `expected error "crash", but was "EOF"`,
},
{
name: "EqualError fails on not equal with format",
require: func(t TestingT) {
EqualError(t, io.EOF, "crash", "pay me %d", 5)
},
expectedLog: `expected error "crash", but was "EOF": pay me 5`,
},
{
name: "Error passes on not nil",
require: func(t TestingT) {
Error(t, io.EOF)
},
},
{
name: "Error fails on nil",
require: func(t TestingT) {
Error(t, nil)
},
expectedLog: "expected an error, but was nil",
},
{
name: "Error fails on nil with format",
require: func(t TestingT) {
Error(t, nil, "pay me %d", 5)
},
expectedLog: `expected an error, but was nil: pay me 5`,
},
{
name: "ErrorIs passes on same",
require: func(t TestingT) {
ErrorIs(t, io.EOF, io.EOF)
},
},
{
name: "ErrorIs passes on wrapped",
require: func(t TestingT) {
ErrorIs(t, fmt.Errorf("cause: %w", io.EOF), io.EOF)
},
},
{
name: "ErrorIs fails on not equal",
require: func(t TestingT) {
ErrorIs(t, io.EOF, io.ErrUnexpectedEOF)
},
expectedLog: "expected errors.Is(EOF, unexpected EOF), but it wasn't",
},
{
name: "ErrorIs fails on not equal with format",
require: func(t TestingT) {
ErrorIs(t, io.EOF, io.ErrUnexpectedEOF, "pay me %d", 5)
},
expectedLog: `expected errors.Is(EOF, unexpected EOF), but it wasn't: pay me 5`,
},
{
name: "Nil passes on nil",
require: func(t TestingT) {
Nil(t, nil)
},
},
{
name: "Nil fails on not nil",
require: func(t TestingT) {
Nil(t, io.EOF)
},
expectedLog: "expected nil, but was EOF",
},
{
name: "Nil fails on not nil with format",
require: func(t TestingT) {
Nil(t, io.EOF, "pay me %d", 5)
},
expectedLog: `expected nil, but was EOF: pay me 5`,
},
{
name: "NoError passes on nil",
require: func(t TestingT) {
NoError(t, nil)
},
},
{
name: "NoError fails on not nil",
require: func(t TestingT) {
NoError(t, io.EOF)
},
expectedLog: "expected no error, but was EOF",
},
{
name: "NoError fails on not nil with format",
require: func(t TestingT) {
NoError(t, io.EOF, "pay me %d", 5)
},
expectedLog: `expected no error, but was EOF: pay me 5`,
},
{
name: "NotNil passes on not nil",
require: func(t TestingT) {
NotNil(t, io.EOF)
},
},
{
name: "NotNil fails on nil",
require: func(t TestingT) {
NotNil(t, nil)
},
expectedLog: "expected to not be nil",
},
{
name: "NotNil fails on nil with format",
require: func(t TestingT) {
NotNil(t, nil, "pay me %d", 5)
},
expectedLog: `expected to not be nil: pay me 5`,
},
{
name: "False passes on false",
require: func(t TestingT) {
False(t, false)
},
},
{
name: "False fails on true",
require: func(t TestingT) {
False(t, true)
},
expectedLog: "expected false, but was true",
},
{
name: "False fails on true with format",
require: func(t TestingT) {
False(t, true, "pay me %d", 5)
},
expectedLog: "expected false, but was true: pay me 5",
},
{
name: "Equal passes on equal: string",
require: func(t TestingT) {
Equal(t, "wazero", "wazero")
},
},
{
name: "Equal passes on equal: []byte",
require: func(t TestingT) {
Equal(t, []byte{1, 2, 3, 4}, []byte{1, 2, 3, 4})
},
},
{
name: "Equal passes on equal: struct",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, &testStruct{name: "takeshi"})
},
},
{
name: "Equal fails on nil: string",
require: func(t TestingT) {
Equal(t, "wazero", nil)
},
expectedLog: `expected "wazero", but was nil`,
},
{
name: "Equal fails on nil: []byte",
require: func(t TestingT) {
Equal(t, []byte{1, 2, 3, 4}, nil)
},
expectedLog: `expected []byte{0x1, 0x2, 0x3, 0x4}, but was nil`,
},
{
name: "Equal fails on nil: struct",
require: func(t TestingT) {
Equal(t, &testStruct{name: "takeshi"}, nil)
},
expectedLog: `expected &require.testStruct{name:"takeshi"}, but was nil`,
},
{
name: "NotEqual passes on not equal",
require: func(t TestingT) {
NotEqual(t, uint32(1), uint32(2))
},
},
{
name: "NotEqual fails on equal: nil",
require: func(t TestingT) {
NotEqual(t, nil, nil)
},
expectedLog: `expected to not equal <nil>`,
},
{
name: "NotEqual fails on equal: string",
require: func(t TestingT) {
NotEqual(t, "wazero", "wazero")
},
expectedLog: `expected to not equal "wazero"`,
},
{
name: "NotEqual fails on equal: []byte",
require: func(t TestingT) {
NotEqual(t, []byte{1, 2, 3, 4}, []byte{1, 2, 3, 4})
},
expectedLog: `expected to not equal []byte{0x1, 0x2, 0x3, 0x4}`,
},
{
name: "NotEqual fails on equal: struct",
require: func(t TestingT) {
NotEqual(t, &testStruct{name: "takeshi"}, &testStruct{name: "takeshi"})
},
expectedLog: `expected to not equal &require.testStruct{name:"takeshi"}`,
},
{
name: "NotEqual fails on equal: struct with format",
require: func(t TestingT) {
NotEqual(t, &testStruct{name: "takeshi"}, &testStruct{name: "takeshi"}, "pay me %d", 5)
},
expectedLog: `expected to not equal &require.testStruct{name:"takeshi"}: pay me 5`,
},
{
name: "NotSame passes on not same",
require: func(t TestingT) {
NotSame(t, struct1, struct2)
},
},
{
name: "NotSame passes on different types",
require: func(t TestingT) {
NotSame(t, struct1, &zero)
},
},
{
name: "NotSame fails on same pointers",
require: func(t TestingT) {
NotSame(t, struct1, struct1)
},
expectedLog: "expected &{hello} to point to a different object",
},
{
name: "NotSame fails on same pointers with format",
require: func(t TestingT) {
NotSame(t, struct1, struct1, "pay me %d", 5)
},
expectedLog: "expected &{hello} to point to a different object: pay me 5",
},
{
name: "Same passes on same",
require: func(t TestingT) {
Same(t, struct1, struct1)
},
},
{
name: "Same fails on different types",
require: func(t TestingT) {
Same(t, struct1, &zero)
},
expectedLog: fmt.Sprintf("expected %v to point to the same object as &{hello}", &zero),
},
{
name: "Same fails on different pointers",
require: func(t TestingT) {
Same(t, struct1, struct2)
},
expectedLog: "expected &{hello} to point to the same object as &{hello}",
},
{
name: "Same fails on different pointers with format",
require: func(t TestingT) {
Same(t, struct1, struct2, "pay me %d", 5)
},
expectedLog: "expected &{hello} to point to the same object as &{hello}: pay me 5",
},
{
name: "True passes on true",
require: func(t TestingT) {
True(t, true)
},
},
{
name: "True fails on false",
require: func(t TestingT) {
True(t, false)
},
expectedLog: "expected true, but was false",
},
{
name: "True fails on false with format",
require: func(t TestingT) {
True(t, false, "pay me %d", 5)
},
expectedLog: "expected true, but was false: pay me 5",
},
{
name: "Zero passes on float32(0)",
require: func(t TestingT) {
Zero(t, float32(0))
},
},
{
name: "Zero passes on float64(0)",
require: func(t TestingT) {
Zero(t, float64(0))
},
},
{
name: "Zero passes on int(0)",
require: func(t TestingT) {
Zero(t, int(0))
},
},
{
name: "Zero passes on uint32(0)",
require: func(t TestingT) {
Zero(t, uint32(0))
},
},
{
name: "Zero passes on uint64(0)",
require: func(t TestingT) {
Zero(t, uint64(0))
},
},
{
name: "Zero fails on float32(1)",
require: func(t TestingT) {
Zero(t, float32(1))
},
expectedLog: "expected zero, but was 1",
},
{
name: "Zero fails on float64(1)",
require: func(t TestingT) {
Zero(t, float64(1))
},
expectedLog: "expected zero, but was 1",
},
{
name: "Zero fails on int(1)",
require: func(t TestingT) {
Zero(t, int(1))
},
expectedLog: "expected zero, but was 1",
},
{
name: "Zero fails on uint32(1)",
require: func(t TestingT) {
Zero(t, uint32(1))
},
expectedLog: "expected zero, but was 1",
},
{
name: "Zero fails on uint64(1)",
require: func(t TestingT) {
Zero(t, uint64(1))
},
expectedLog: "expected zero, but was 1",
},
{
name: "Zero fails on uint64(1) with format",
require: func(t TestingT) {
Zero(t, uint64(1), "pay me %d", 5)
},
expectedLog: "expected zero, but was 1: pay me 5",
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
m := &mockT{t: t}
tc.require(m)
m.require(tc.expectedLog)
})
}
}
// compile-time check to ensure mockT implements TestingT
var _ TestingT = &mockT{}
type mockT struct {
t *testing.T
log string
}
// Fatal implements TestingT.Fatal
func (t *mockT) Fatal(args ...interface{}) {
if t.log != "" {
t.t.Fatal("already called Fatal(")
}
t.log = fmt.Sprint(args...)
}
func (t *mockT) require(expectedLog string) {
if expectedLog != t.log {
t.t.Fatalf("expected log=%q, but found %q", expectedLog, t.log)
}
}