Этот коммит содержится в:
Christopher Speller
2018-01-29 14:17:40 -08:00
коммит произвёл GitHub
родитель 8d66523ba7
Коммит 961c04cae9
1508 изменённых файлов: 182081 добавлений и 24688 удалений

141
vendor/github.com/stretchr/testify/mock/mock.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,7 @@
package mock
import (
"errors"
"fmt"
"reflect"
"regexp"
@@ -15,10 +16,6 @@ import (
"github.com/stretchr/testify/assert"
)
func inin() {
spew.Config.SortKeys = true
}
// TestingT is an interface wrapper around *testing.T
type TestingT interface {
Logf(format string, args ...interface{})
@@ -52,10 +49,15 @@ type Call struct {
// Amount of times this call has been called
totalCalls int
// Call to this method can be optional
optional bool
// Holds a channel that will be used to block the Return until it either
// receives a message or is closed. nil means it returns immediately.
WaitFor <-chan time.Time
waitTime time.Duration
// Holds a handler used to manipulate arguments content that are passed by
// reference. It's useful when mocking methods such as unmarshalers or
// decoders.
@@ -134,7 +136,10 @@ func (c *Call) WaitUntil(w <-chan time.Time) *Call {
//
// Mock.On("MyMethod", arg1, arg2).After(time.Second)
func (c *Call) After(d time.Duration) *Call {
return c.WaitUntil(time.After(d))
c.lock()
defer c.unlock()
c.waitTime = d
return c
}
// Run sets a handler to be called before returning. It can be used when
@@ -145,13 +150,22 @@ func (c *Call) After(d time.Duration) *Call {
// arg := args.Get(0).(*map[string]interface{})
// arg["foo"] = "bar"
// })
func (c *Call) Run(fn func(Arguments)) *Call {
func (c *Call) Run(fn func(args Arguments)) *Call {
c.lock()
defer c.unlock()
c.RunFn = fn
return c
}
// Maybe allows the method call to be optional. Not calling an optional method
// will not cause an error while asserting expectations
func (c *Call) Maybe() *Call {
c.lock()
defer c.unlock()
c.optional = true
return c
}
// On chains a new expectation description onto the mocked interface. This
// allows syntax like.
//
@@ -218,8 +232,6 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
// */
func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
m.mutex.Lock()
defer m.mutex.Unlock()
for i, call := range m.ExpectedCalls {
if call.Method == method && call.Repeatability > -1 {
@@ -283,7 +295,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
functionPath := runtime.FuncForPC(pc).Name()
//Next four lines are required to use GCCGO function naming conventions.
//For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
//uses inteface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
//uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
//With GCCGO we need to remove interface information starting from pN<dd>.
re := regexp.MustCompile("\\.pN\\d+_")
if re.MatchString(functionPath) {
@@ -291,8 +303,16 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
}
parts := strings.Split(functionPath, ".")
functionName := parts[len(parts)-1]
return m.MethodCalled(functionName, arguments...)
}
found, call := m.findExpectedCall(functionName, arguments...)
// MethodCalled tells the mock object that the given method has been called, and gets
// an array of arguments to return. Panics if the call is unexpected (i.e. not preceded
// by appropriate .On .Return() calls)
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
m.mutex.Lock()
found, call := m.findExpectedCall(methodName, arguments...)
if found < 0 {
// we have to fail here - because we don't know what to do
@@ -302,45 +322,47 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
// b) the arguments are not what was expected, or
// c) the developer has forgotten to add an accompanying On...Return pair.
closestFound, closestCall := m.findClosestCall(functionName, arguments...)
closestFound, closestCall := m.findClosestCall(methodName, arguments...)
m.mutex.Unlock()
if closestFound {
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\n", callString(functionName, arguments, true), callString(functionName, closestCall.Arguments, true), diffArguments(arguments, closestCall.Arguments)))
panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n\n%s\n", callString(methodName, arguments, true), callString(methodName, closestCall.Arguments, true), diffArguments(closestCall.Arguments, arguments)))
} else {
panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", functionName, functionName, callString(functionName, arguments, true), assert.CallerInfo()))
panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", methodName, methodName, callString(methodName, arguments, true), assert.CallerInfo()))
}
} else {
m.mutex.Lock()
switch {
case call.Repeatability == 1:
call.Repeatability = -1
call.totalCalls++
case call.Repeatability > 1:
call.Repeatability--
call.totalCalls++
case call.Repeatability == 0:
call.totalCalls++
}
m.mutex.Unlock()
}
if call.Repeatability == 1 {
call.Repeatability = -1
} else if call.Repeatability > 1 {
call.Repeatability--
}
call.totalCalls++
// add the call
m.mutex.Lock()
m.Calls = append(m.Calls, *newCall(m, functionName, arguments...))
m.Calls = append(m.Calls, *newCall(m, methodName, arguments...))
m.mutex.Unlock()
// block if specified
if call.WaitFor != nil {
<-call.WaitFor
} else {
time.Sleep(call.waitTime)
}
if call.RunFn != nil {
call.RunFn(arguments)
m.mutex.Lock()
runFn := call.RunFn
m.mutex.Unlock()
if runFn != nil {
runFn(arguments)
}
return call.ReturnArguments
m.mutex.Lock()
returnArgs := call.ReturnArguments
m.mutex.Unlock()
return returnArgs
}
/*
@@ -372,25 +394,25 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
// AssertExpectations asserts that everything specified with On and Return was
// in fact called as expected. Calls may have occurred in any order.
func (m *Mock) AssertExpectations(t TestingT) bool {
m.mutex.Lock()
defer m.mutex.Unlock()
var somethingMissing bool
var failedExpectations int
// iterate through each expectation
expectedCalls := m.expectedCalls()
for _, expectedCall := range expectedCalls {
if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
somethingMissing = true
failedExpectations++
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
} else {
m.mutex.Lock()
if expectedCall.Repeatability > 0 {
somethingMissing = true
failedExpectations++
} else {
t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
}
m.mutex.Unlock()
}
}
@@ -403,6 +425,8 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
m.mutex.Lock()
defer m.mutex.Unlock()
var actualCalls int
for _, call := range m.calls() {
if call.Method == methodName {
@@ -415,6 +439,8 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls
// AssertCalled asserts that the method was called.
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
m.mutex.Lock()
defer m.mutex.Unlock()
if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
t.Logf("%v", m.expectedCalls())
return false
@@ -425,6 +451,8 @@ func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interfac
// AssertNotCalled asserts that the method was not called.
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
m.mutex.Lock()
defer m.mutex.Unlock()
if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
t.Logf("%v", m.expectedCalls())
return false
@@ -450,14 +478,10 @@ func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
}
func (m *Mock) expectedCalls() []*Call {
m.mutex.Lock()
defer m.mutex.Unlock()
return append([]*Call{}, m.ExpectedCalls...)
}
func (m *Mock) calls() []Call {
m.mutex.Lock()
defer m.mutex.Unlock()
return append([]Call{}, m.Calls...)
}
@@ -496,9 +520,25 @@ type argumentMatcher struct {
func (f argumentMatcher) Matches(argument interface{}) bool {
expectType := f.fn.Type().In(0)
expectTypeNilSupported := false
switch expectType.Kind() {
case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Ptr:
expectTypeNilSupported = true
}
if reflect.TypeOf(argument).AssignableTo(expectType) {
result := f.fn.Call([]reflect.Value{reflect.ValueOf(argument)})
argType := reflect.TypeOf(argument)
var arg reflect.Value
if argType == nil {
arg = reflect.New(expectType).Elem()
} else {
arg = reflect.ValueOf(argument)
}
if argType == nil && !expectTypeNilSupported {
panic(errors.New("attempting to call matcher with nil for non-nil expected type"))
}
if argType == nil || argType.AssignableTo(expectType) {
result := f.fn.Call([]reflect.Value{arg})
return result[0].Bool()
}
return false
@@ -518,7 +558,7 @@ func (f argumentMatcher) String() string {
//
// |fn|, must be a function accepting a single argument (of the expected type)
// which returns a bool. If |fn| doesn't match the required signature,
// MathedBy() panics.
// MatchedBy() panics.
func MatchedBy(fn interface{}) argumentMatcher {
fnType := reflect.TypeOf(fn)
@@ -719,6 +759,10 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
}
func diffArguments(expected Arguments, actual Arguments) string {
if len(expected) != len(actual) {
return fmt.Sprintf("Provided %v arguments, mocked for %v arguments", len(expected), len(actual))
}
for x := range expected {
if diffString := diff(expected[x], actual[x]); diffString != "" {
return fmt.Sprintf("Difference found in argument %v:\n\n%s", x, diffString)
@@ -746,8 +790,8 @@ func diff(expected interface{}, actual interface{}) string {
return ""
}
e := spew.Sdump(expected)
a := spew.Sdump(actual)
e := spewConfig.Sdump(expected)
a := spewConfig.Sdump(actual)
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
A: difflib.SplitLines(e),
@@ -761,3 +805,10 @@ func diff(expected interface{}, actual interface{}) string {
return diff
}
var spewConfig = spew.ConfigState{
Indent: " ",
DisablePointerAddresses: true,
DisableCapacities: true,
SortKeys: true,
}

236
vendor/github.com/stretchr/testify/mock/mock_test.go сгенерированный поставляемый
Просмотреть файл

@@ -2,10 +2,13 @@ package mock
import (
"errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"fmt"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
/*
@@ -40,6 +43,26 @@ func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error {
return args.Error(0)
}
func (i *TestExampleImplementation) TheExampleMethod4(v ExampleInterface) error {
args := i.Called(v)
return args.Error(0)
}
func (i *TestExampleImplementation) TheExampleMethod5(ch chan struct{}) error {
args := i.Called(ch)
return args.Error(0)
}
func (i *TestExampleImplementation) TheExampleMethod6(m map[string]bool) error {
args := i.Called(m)
return args.Error(0)
}
func (i *TestExampleImplementation) TheExampleMethod7(slice []bool) error {
args := i.Called(slice)
return args.Error(0)
}
func (i *TestExampleImplementation) TheExampleMethodFunc(fn func(string) error) error {
args := i.Called(fn)
return args.Error(0)
@@ -55,6 +78,11 @@ func (i *TestExampleImplementation) TheExampleMethodVariadicInterface(a ...inter
return args.Error(0)
}
func (i *TestExampleImplementation) TheExampleMethodMixedVariadic(a int, b ...int) error {
args := i.Called(a, b)
return args.Error(0)
}
type ExampleFuncType func(string) error
func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) error {
@@ -174,15 +202,20 @@ func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod3",
MatchedBy(func(a *ExampleType) bool { return a.ran == true }),
MatchedBy(func(a *ExampleType) bool { return a != nil && a.ran == true }),
).Return(nil)
mockedService.On("TheExampleMethod3",
MatchedBy(func(a *ExampleType) bool { return a.ran == false }),
MatchedBy(func(a *ExampleType) bool { return a != nil && a.ran == false }),
).Return(errors.New("error"))
mockedService.On("TheExampleMethod3",
MatchedBy(func(a *ExampleType) bool { return a == nil }),
).Return(errors.New("error2"))
assert.Equal(t, mockedService.TheExampleMethod3(&ExampleType{true}), nil)
assert.EqualError(t, mockedService.TheExampleMethod3(&ExampleType{false}), "error")
assert.EqualError(t, mockedService.TheExampleMethod3(nil), "error2")
}
func Test_Mock_On_WithFuncArgMatcher(t *testing.T) {
@@ -191,17 +224,62 @@ func Test_Mock_On_WithFuncArgMatcher(t *testing.T) {
fixture1, fixture2 := errors.New("fixture1"), errors.New("fixture2")
mockedService.On("TheExampleMethodFunc",
MatchedBy(func(a func(string) error) bool { return a("string") == fixture1 }),
MatchedBy(func(a func(string) error) bool { return a != nil && a("string") == fixture1 }),
).Return(errors.New("fixture1"))
mockedService.On("TheExampleMethodFunc",
MatchedBy(func(a func(string) error) bool { return a("string") == fixture2 }),
MatchedBy(func(a func(string) error) bool { return a != nil && a("string") == fixture2 }),
).Return(errors.New("fixture2"))
mockedService.On("TheExampleMethodFunc",
MatchedBy(func(a func(string) error) bool { return a == nil }),
).Return(errors.New("fixture3"))
assert.EqualError(t, mockedService.TheExampleMethodFunc(
func(string) error { return fixture1 }), "fixture1")
assert.EqualError(t, mockedService.TheExampleMethodFunc(
func(string) error { return fixture2 }), "fixture2")
assert.EqualError(t, mockedService.TheExampleMethodFunc(nil), "fixture3")
}
func Test_Mock_On_WithInterfaceArgMatcher(t *testing.T) {
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod4",
MatchedBy(func(a ExampleInterface) bool { return a == nil }),
).Return(errors.New("fixture1"))
assert.EqualError(t, mockedService.TheExampleMethod4(nil), "fixture1")
}
func Test_Mock_On_WithChannelArgMatcher(t *testing.T) {
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod5",
MatchedBy(func(ch chan struct{}) bool { return ch == nil }),
).Return(errors.New("fixture1"))
assert.EqualError(t, mockedService.TheExampleMethod5(nil), "fixture1")
}
func Test_Mock_On_WithMapArgMatcher(t *testing.T) {
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod6",
MatchedBy(func(m map[string]bool) bool { return m == nil }),
).Return(errors.New("fixture1"))
assert.EqualError(t, mockedService.TheExampleMethod6(nil), "fixture1")
}
func Test_Mock_On_WithSliceArgMatcher(t *testing.T) {
var mockedService TestExampleImplementation
mockedService.On("TheExampleMethod7",
MatchedBy(func(slice []bool) bool { return slice == nil }),
).Return(errors.New("fixture1"))
assert.EqualError(t, mockedService.TheExampleMethod7(nil), "fixture1")
}
func Test_Mock_On_WithVariadicFunc(t *testing.T) {
@@ -226,6 +304,29 @@ func Test_Mock_On_WithVariadicFunc(t *testing.T) {
}
func Test_Mock_On_WithMixedVariadicFunc(t *testing.T) {
// make a test impl object
var mockedService = new(TestExampleImplementation)
c := mockedService.
On("TheExampleMethodMixedVariadic", 1, []int{2, 3, 4}).
Return(nil)
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
assert.Equal(t, 2, len(c.Arguments))
assert.Equal(t, 1, c.Arguments[0])
assert.Equal(t, []int{2, 3, 4}, c.Arguments[1])
assert.NotPanics(t, func() {
mockedService.TheExampleMethodMixedVariadic(1, 2, 3, 4)
})
assert.Panics(t, func() {
mockedService.TheExampleMethodMixedVariadic(1, 2, 3, 5)
})
}
func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
// make a test impl object
@@ -726,7 +827,7 @@ func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
mockedService2.Called(2)
mockedService3.Called(3)
assert.True(t, AssertExpectationsForObjects(t, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock))
assert.True(t, AssertExpectationsForObjects(t, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock))
assert.True(t, AssertExpectationsForObjects(t, mockedService1, mockedService2, mockedService3))
}
@@ -745,7 +846,7 @@ func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
mockedService3.Called(3)
tt := new(testing.T)
assert.False(t, AssertExpectationsForObjects(tt, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock))
assert.False(t, AssertExpectationsForObjects(tt, &mockedService1.Mock, &mockedService2.Mock, &mockedService3.Mock))
assert.False(t, AssertExpectationsForObjects(tt, mockedService1, mockedService2, mockedService3))
}
@@ -969,6 +1070,31 @@ func Test_Mock_AssertNotCalled(t *testing.T) {
}
func Test_Mock_AssertOptional(t *testing.T) {
// Optional called
var ms1 = new(TestExampleImplementation)
ms1.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil)
ms1.TheExampleMethod(1, 2, 3)
tt1 := new(testing.T)
assert.Equal(t, true, ms1.AssertExpectations(tt1))
// Optional not called
var ms2 = new(TestExampleImplementation)
ms2.On("TheExampleMethod", 1, 2, 3).Maybe().Return(4, nil)
tt2 := new(testing.T)
assert.Equal(t, true, ms2.AssertExpectations(tt2))
// Non-optional called
var ms3 = new(TestExampleImplementation)
ms3.On("TheExampleMethod", 1, 2, 3).Return(4, nil)
ms3.TheExampleMethod(1, 2, 3)
tt3 := new(testing.T)
assert.Equal(t, true, ms3.AssertExpectations(tt3))
}
/*
Arguments helper methods
*/
@@ -1130,3 +1256,97 @@ func Test_Arguments_Bool(t *testing.T) {
assert.Equal(t, true, args.Bool(2))
}
func Test_WaitUntil_Parallel(t *testing.T) {
// make a test impl object
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
ch1 := make(chan time.Time)
ch2 := make(chan time.Time)
mockedService.Mock.On("TheExampleMethod2", true).Return().WaitUntil(ch2).Run(func(args Arguments) {
ch1 <- time.Now()
})
mockedService.Mock.On("TheExampleMethod2", false).Return().WaitUntil(ch1)
// Lock both goroutines on the .WaitUntil method
go func() {
mockedService.TheExampleMethod2(false)
}()
go func() {
mockedService.TheExampleMethod2(true)
}()
// Allow the first call to execute, so the second one executes afterwards
ch2 <- time.Now()
}
func Test_MockMethodCalled(t *testing.T) {
m := new(Mock)
m.On("foo", "hello").Return("world")
retArgs := m.MethodCalled("foo", "hello")
require.True(t, len(retArgs) == 1)
require.Equal(t, "world", retArgs[0])
m.AssertExpectations(t)
}
// Test to validate fix for racy concurrent call access in MethodCalled()
func Test_MockReturnAndCalledConcurrent(t *testing.T) {
iterations := 1000
m := &Mock{}
call := m.On("ConcurrencyTestMethod")
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
for i := 0; i < iterations; i++ {
call.Return(10)
}
wg.Done()
}()
go func() {
for i := 0; i < iterations; i++ {
ConcurrencyTestMethod(m)
}
wg.Done()
}()
wg.Wait()
}
type timer struct{ Mock }
func (s *timer) GetTime(i int) string {
return s.Called(i).Get(0).(string)
}
func TestAfterTotalWaitTimeWhileExecution(t *testing.T) {
waitDuration := 1
total, waitMs := 5, time.Millisecond*time.Duration(waitDuration)
aTimer := new(timer)
for i := 0; i < total; i++ {
aTimer.On("GetTime", i).After(waitMs).Return(fmt.Sprintf("Time%d", i)).Once()
}
time.Sleep(waitMs)
start := time.Now()
var results []string
for i := 0; i < total; i++ {
results = append(results, aTimer.GetTime(i))
}
end := time.Now()
elapsedTime := end.Sub(start)
assert.True(t, elapsedTime > waitMs, fmt.Sprintf("Total elapsed time:%v should be atleast greater than %v", elapsedTime, waitMs))
assert.Equal(t, total, len(results))
for i, _ := range results {
assert.Equal(t, fmt.Sprintf("Time%d", i), results[i], "Return value of method should be same")
}
}
func ConcurrencyTestMethod(m *Mock) {
m.Called()
}