diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 03eb7e0d061..5f30ed59f74 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -462,15 +462,15 @@ }, { "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + "Rev": "7e4a149930b09fe4c2b134c50ce637457ba6e966" }, { "ImportPath": "github.com/stretchr/testify/mock", - "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + "Rev": "7e4a149930b09fe4c2b134c50ce637457ba6e966" }, { "ImportPath": "github.com/stretchr/testify/require", - "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + "Rev": "7e4a149930b09fe4c2b134c50ce637457ba6e966" }, { "ImportPath": "github.com/syndtr/gocapability/capability", diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go index 58e1781651a..7b5ce7257e0 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go @@ -4,11 +4,14 @@ import ( "bufio" "bytes" "fmt" + "math" "reflect" "regexp" "runtime" "strings" "time" + "unicode" + "unicode/utf8" ) // TestingT is an interface wrapper around *testing.T @@ -36,15 +39,12 @@ func ObjectsAreEqual(expected, actual interface{}) bool { return true } - // Last ditch effort - if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) { - return true - } - return false } +// ObjectsAreEqualValues gets whether two objects are equal, or if their +// values are equal. func ObjectsAreEqualValues(expected, actual interface{}) bool { if ObjectsAreEqual(expected, actual) { return true @@ -66,28 +66,62 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool { internally, causing it to print the file:line of the assert method, rather than where the problem actually occured in calling code.*/ -// CallerInfo returns a string containing the file and line number of the assert call -// that failed. -func CallerInfo() string { +// CallerInfo returns an array of strings containing the file and line number +// of each stack frame leading from the current test to the assert call that +// failed. +func CallerInfo() []string { + pc := uintptr(0) file := "" line := 0 ok := false + name := "" + callers := []string{} for i := 0; ; i++ { - _, file, line, ok = runtime.Caller(i) + pc, file, line, ok = runtime.Caller(i) if !ok { - return "" + return nil } + parts := strings.Split(file, "/") dir := parts[len(parts)-2] file = parts[len(parts)-1] if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + // Drop the package + segments := strings.Split(name, ".") + name = segments[len(segments)-1] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { break } } - return fmt.Sprintf("%s:%d", file, line) + return callers +} + +// Stolen from the `go test` tool. +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) } // getWhitespaceString returns a string that is long enough to overwrite the default @@ -146,19 +180,20 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { message := messageFromMsgAndArgs(msgAndArgs...) + errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t") if len(message) > 0 { - t.Errorf("\r%s\r\tLocation:\t%s\n"+ + t.Errorf("\r%s\r\tError Trace:\t%s\n"+ "\r\tError:%s\n"+ "\r\tMessages:\t%s\n\r", getWhitespaceString(), - CallerInfo(), + errorTrace, indentMessageLines(failureMessage, 2), message) } else { - t.Errorf("\r%s\r\tLocation:\t%s\n"+ + t.Errorf("\r%s\r\tError Trace:\t%s\n"+ "\r\tError:%s\n\r", getWhitespaceString(), - CallerInfo(), + errorTrace, indentMessageLines(failureMessage, 2)) } @@ -659,6 +694,14 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) } + if math.IsNaN(af) { + return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...) + } + + if math.IsNaN(bf) { + return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) + } + dt := af - bf if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) @@ -667,6 +710,27 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs return true } +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta) + if !result { + return result + } + } + + return true +} + // min(|expected|, |actual|) * epsilon func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 { af, aok := toFloat(expected) @@ -701,6 +765,27 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd return InDelta(t, expected, actual, delta, msgAndArgs...) } +// InEpsilonSlice is the same as InEpsilon, except it compares two slices. +func InEpsilonSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta) + if !result { + return result + } + } + + return true +} + /* Errors */ diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go index 2cb58dbd74f..d859c77b912 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go @@ -2,6 +2,7 @@ package assert import ( "errors" + "math" "regexp" "testing" "time" @@ -115,10 +116,6 @@ func TestEqual(t *testing.T) { if !Equal(mockT, uint64(123), uint64(123)) { t.Error("Equal should return true") } - funcA := func() int { return 42 } - if !Equal(mockT, funcA, funcA) { - t.Error("Equal should return true") - } } @@ -406,19 +403,6 @@ func TestNotPanics(t *testing.T) { } -func TestEqual_Funcs(t *testing.T) { - - type f func() int - f1 := func() int { return 1 } - f2 := func() int { return 2 } - - f1Copy := f1 - - Equal(t, f1Copy, f1, "Funcs are the same and should be considered equal") - NotEqual(t, f1, f2, "f1 and f2 are different") - -} - func TestNoError(t *testing.T) { mockT := new(testing.T) @@ -669,6 +653,8 @@ func TestInDelta(t *testing.T) { False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail") + False(t, InDelta(mockT, 42, math.NaN(), 0.01), "Expected NaN for actual to fail") + False(t, InDelta(mockT, math.NaN(), 42, 0.01), "Expected NaN for expected to fail") cases := []struct { a, b interface{} @@ -694,6 +680,27 @@ func TestInDelta(t *testing.T) { } } +func TestInDeltaSlice(t *testing.T) { + mockT := new(testing.T) + + True(t, InDeltaSlice(mockT, + []float64{1.001, 0.999}, + []float64{1, 1}, + 0.1), "{1.001, 0.009} is element-wise close to {1, 1} in delta=0.1") + + True(t, InDeltaSlice(mockT, + []float64{1, 2}, + []float64{0, 3}, + 1), "{1, 2} is element-wise close to {0, 3} in delta=1") + + False(t, InDeltaSlice(mockT, + []float64{1, 2}, + []float64{0, 3}, + 0.1), "{1, 2} is not element-wise close to {0, 3} in delta=0.1") + + False(t, InDeltaSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") +} + func TestInEpsilon(t *testing.T) { mockT := new(testing.T) @@ -733,6 +740,22 @@ func TestInEpsilon(t *testing.T) { } +func TestInEpsilonSlice(t *testing.T) { + mockT := new(testing.T) + + True(t, InEpsilonSlice(mockT, + []float64{2.2, 2.0}, + []float64{2.1, 2.1}, + 0.06), "{2.2, 2.0} is element-wise close to {2.1, 2.1} in espilon=0.06") + + False(t, InEpsilonSlice(mockT, + []float64{2.2, 2.0}, + []float64{2.1, 2.1}, + 0.04), "{2.2, 2.0} is not element-wise close to {2.1, 2.1} in espilon=0.04") + + False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") +} + func TestRegexp(t *testing.T) { mockT := new(testing.T) diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go index 1c6de283d0b..f678106287b 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go @@ -1,4 +1,4 @@ -// A set of comprehensive testing tools for use with the normal Go testing system. +// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // // Example Usage // @@ -45,7 +45,9 @@ // // Here is an overview of the assert functions: // -// assert.Equal(t, expected, actual [, message [, format-args]) +// assert.Equal(t, expected, actual [, message [, format-args]]) +// +// assert.EqualValues(t, expected, actual [, message [, format-args]]) // // assert.NotEqual(t, notExpected, actual [, message [, format-args]]) // @@ -98,7 +100,9 @@ // assert package contains Assertions object. it has assertion methods. // // Here is an overview of the assert functions: -// assert.Equal(expected, actual [, message [, format-args]) +// assert.Equal(expected, actual [, message [, format-args]]) +// +// assert.EqualValues(expected, actual [, message [, format-args]]) // // assert.NotEqual(notExpected, actual [, message [, format-args]]) // diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go index 67a6925a1e6..d8d3f531ea1 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go @@ -2,10 +2,13 @@ package assert import "time" +// Assertions provides assertion methods around the +// TestingT interface. type Assertions struct { t TestingT } +// New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, @@ -85,7 +88,7 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { return Empty(a.t, object, msgAndArgs...) } -// Empty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a // slice with len == 0. // // if assert.NotEmpty(obj) { @@ -152,7 +155,7 @@ func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interfac return NotContains(a.t, s, contains, msgAndArgs...) } -// Uses a Comparison to assert a complex condition. +// Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { return Condition(a.t, comp, msgAndArgs...) } diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go index 0dac6c7ae15..3df3f3917ac 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go @@ -259,27 +259,12 @@ func TestNotPanicsWrapper(t *testing.T) { } -func TestEqualWrapper_Funcs(t *testing.T) { - - assert := New(t) - - type f func() int - var f1 f = func() int { return 1 } - var f2 f = func() int { return 2 } - - var f1_copy f = f1 - - assert.Equal(f1_copy, f1, "Funcs are the same and should be considered equal") - assert.NotEqual(f1, f2, "f1 and f2 are different") - -} - func TestNoErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error - var err error = nil + var err error assert.True(mockAssert.NoError(err), "NoError should return True for nil arg") @@ -295,7 +280,7 @@ func TestErrorWrapper(t *testing.T) { mockAssert := New(new(testing.T)) // start with a nil error - var err error = nil + var err error assert.False(mockAssert.Error(err), "Error should return False for nil arg") diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go index 0419c1b60bc..1246e58e0ef 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go @@ -59,9 +59,9 @@ func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values ur return code >= http.StatusBadRequest } -// HttpBody is a helper that returns HTTP body of the response. It returns +// HTTPBody is a helper that returns HTTP body of the response. It returns // empty string if building a new request fails. -func HttpBody(handler http.HandlerFunc, mode, url string, values url.Values) string { +func HTTPBody(handler http.HandlerFunc, mode, url string, values url.Values) string { w := httptest.NewRecorder() req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil) if err != nil { @@ -78,7 +78,7 @@ func HttpBody(handler http.HandlerFunc, mode, url string, values url.Values) str // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { - body := HttpBody(handler, mode, url, values) + body := HTTPBody(handler, mode, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if !contains { @@ -95,7 +95,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, va // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { - body := HttpBody(handler, mode, url, values) + body := HTTPBody(handler, mode, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if contains { diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go index f73fa2516b5..007643f624f 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go @@ -2,12 +2,14 @@ package mock import ( "fmt" - "github.com/stretchr/objx" - "github.com/stretchr/testify/assert" "reflect" "runtime" "strings" "sync" + "time" + + "github.com/stretchr/objx" + "github.com/stretchr/testify/assert" ) // TestingT is an interface wrapper around *testing.T @@ -37,6 +39,15 @@ type Call struct { // The number of times to return the return arguments when setting // expectations. 0 means to always return the value. Repeatability int + + // Holds a channel that will be used to block the Return until it either + // recieves a message or is closed. nil means it returns immediately. + WaitFor <-chan time.Time + + // Holds a handler used to manipulate arguments content that are passed by + // reference. It's useful when mocking methods such as unmarshalers or + // decoders. + Run func(Arguments) } // Mock is the workhorse used to track activity on another object. @@ -87,6 +98,13 @@ func (m *Mock) TestData() objx.Map { func (m *Mock) On(methodName string, arguments ...interface{}) *Mock { m.onMethodName = methodName m.onMethodArguments = arguments + + for _, arg := range arguments { + if v := reflect.ValueOf(arg); v.Kind() == reflect.Func { + panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg)) + } + } + return m } @@ -95,7 +113,10 @@ func (m *Mock) On(methodName string, arguments ...interface{}) *Mock { // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2) func (m *Mock) Return(returnArguments ...interface{}) *Mock { - m.ExpectedCalls = append(m.ExpectedCalls, Call{m.onMethodName, m.onMethodArguments, returnArguments, 0}) + m.mutex.Lock() + defer m.mutex.Unlock() + + m.ExpectedCalls = append(m.ExpectedCalls, Call{m.onMethodName, m.onMethodArguments, returnArguments, 0, nil, nil}) return m } @@ -103,14 +124,18 @@ func (m *Mock) Return(returnArguments ...interface{}) *Mock { // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() func (m *Mock) Once() { + m.mutex.Lock() m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 1 + m.mutex.Unlock() } // Twice indicates that that the mock should only return the value twice. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() func (m *Mock) Twice() { + m.mutex.Lock() m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 2 + m.mutex.Unlock() } // Times indicates that that the mock should only return the indicated number @@ -118,7 +143,42 @@ func (m *Mock) Twice() { // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) func (m *Mock) Times(i int) { + m.mutex.Lock() m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = i + m.mutex.Unlock() +} + +// WaitUntil sets the channel that will block the mock's return until its closed +// or a message is received. +// +// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second)) +func (m *Mock) WaitUntil(w <-chan time.Time) *Mock { + m.mutex.Lock() + m.ExpectedCalls[len(m.ExpectedCalls)-1].WaitFor = w + m.mutex.Unlock() + return m +} + +// After sets how long to block until the call returns +// +// Mock.On("MyMethod", arg1, arg2).After(time.Second) +func (m *Mock) After(d time.Duration) *Mock { + return m.WaitUntil(time.After(d)) +} + +// Run sets a handler to be called before returning. It can be used when +// mocking a method such as unmarshalers that takes a pointer to a struct and +// sets properties in such struct +// +// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(function(args Arguments) { +// arg := args.Get(0).(*map[string]interface{}) +// arg["foo"] = "bar" +// }) +func (m *Mock) Run(fn func(Arguments)) *Mock { + m.mutex.Lock() + m.ExpectedCalls[len(m.ExpectedCalls)-1].Run = fn + m.mutex.Unlock() + return m } /* @@ -126,7 +186,7 @@ func (m *Mock) Times(i int) { */ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) { - for i, call := range m.ExpectedCalls { + for i, call := range m.expectedCalls() { if call.Method == method && call.Repeatability > -1 { _, diffCount := call.Arguments.Diff(arguments) @@ -140,11 +200,10 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, * } func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) { - diffCount := 0 var closestCall *Call = nil - for _, call := range m.ExpectedCalls { + for _, call := range m.expectedCalls() { if call.Method == method { _, tempDiffCount := call.Arguments.Diff(arguments) @@ -180,10 +239,8 @@ func callString(method string, arguments Arguments, includeArgumentValues bool) // Called tells the mock object that a method has been called, and gets an array // of arguments to return. Panics if the call is unexpected (i.e. not preceeded by // appropriate .On .Return() calls) +// If Call.WaitFor is set, blocks until the channel is closed or receives a message. func (m *Mock) Called(arguments ...interface{}) Arguments { - defer m.mutex.Unlock() - m.mutex.Lock() - // get the calling function's name pc, _, _, ok := runtime.Caller(1) if !ok { @@ -195,8 +252,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments { found, call := m.findExpectedCall(functionName, arguments...) - switch { - case found < 0: + if found < 0 { // we have to fail here - because we don't know what to do // as the return arguments. This is because: // @@ -211,16 +267,32 @@ func (m *Mock) Called(arguments ...interface{}) 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())) } - case call.Repeatability == 1: - call.Repeatability = -1 - m.ExpectedCalls[found] = *call - case call.Repeatability > 1: - call.Repeatability -= 1 - m.ExpectedCalls[found] = *call + } else { + m.mutex.Lock() + switch { + case call.Repeatability == 1: + call.Repeatability = -1 + m.ExpectedCalls[found] = *call + case call.Repeatability > 1: + call.Repeatability -= 1 + m.ExpectedCalls[found] = *call + } + m.mutex.Unlock() } // add the call - m.Calls = append(m.Calls, Call{functionName, arguments, make([]interface{}, 0), 0}) + m.mutex.Lock() + m.Calls = append(m.Calls, Call{functionName, arguments, make([]interface{}, 0), 0, nil, nil}) + m.mutex.Unlock() + + // block if specified + if call.WaitFor != nil { + <-call.WaitFor + } + + if call.Run != nil { + call.Run(arguments) + } return call.ReturnArguments @@ -246,12 +318,12 @@ 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 { - var somethingMissing bool = false var failedExpectations int = 0 // iterate through each expectation - for _, expectedCall := range m.ExpectedCalls { + expectedCalls := m.expectedCalls() + for _, expectedCall := range expectedCalls { switch { case !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments): somethingMissing = true @@ -266,7 +338,7 @@ func (m *Mock) AssertExpectations(t TestingT) bool { } if somethingMissing { - t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(m.ExpectedCalls)-failedExpectations, len(m.ExpectedCalls), failedExpectations, assert.CallerInfo()) + t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo()) } return !somethingMissing @@ -275,7 +347,7 @@ 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 { var actualCalls int = 0 - for _, call := range m.Calls { + for _, call := range m.calls() { if call.Method == methodName { actualCalls++ } @@ -286,7 +358,7 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls // AssertCalled asserts that the method was called. func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool { 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("%s", m.ExpectedCalls) + t.Logf("%v", m.expectedCalls()) return false } return true @@ -295,14 +367,14 @@ func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interfac // AssertNotCalled asserts that the method was not called. func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool { 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("%s", m.ExpectedCalls) + t.Logf("%v", m.expectedCalls()) return false } return true } func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool { - for _, call := range m.Calls { + for _, call := range m.calls() { if call.Method == methodName { _, differences := Arguments(expected).Diff(call.Arguments) @@ -318,6 +390,18 @@ func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool { return false } +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...) +} + /* Arguments */ diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go index a4457e07107..b1ee9545165 100644 --- a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go +++ b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go @@ -4,6 +4,7 @@ import ( "errors" "github.com/stretchr/testify/assert" "testing" + "time" ) /* @@ -29,13 +30,37 @@ func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) { i.Called(yesorno) } -type ExampleType struct{} +type ExampleType struct { + ran bool +} func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error { args := i.Called(et) return args.Error(0) } +func (i *TestExampleImplementation) TheExampleMethodFunc(fn func(string) error) error { + args := i.Called(fn) + return args.Error(0) +} + +func (i *TestExampleImplementation) TheExampleMethodVariadic(a ...int) error { + args := i.Called(a) + return args.Error(0) +} + +func (i *TestExampleImplementation) TheExampleMethodVariadicInterface(a ...interface{}) error { + args := i.Called(a) + return args.Error(0) +} + +type ExampleFuncType func(string) error + +func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType) error { + args := i.Called(fn) + return args.Error(0) +} + /* Mock */ @@ -76,6 +101,98 @@ func Test_Mock_On_WithArgs(t *testing.T) { } +func Test_Mock_On_WithFuncArg(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethodFunc", AnythingOfType("func(string) error")).Return(nil), &mockedService.Mock) + assert.Equal(t, "TheExampleMethodFunc", mockedService.onMethodName) + assert.Equal(t, AnythingOfType("func(string) error"), mockedService.onMethodArguments[0]) + + fn := func(string) error { return nil } + mockedService.TheExampleMethodFunc(fn) + +} + +func Test_Mock_On_WithVariadicFunc(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethodVariadic", []int{1, 2, 3}).Return(nil), &mockedService.Mock) + assert.Equal(t, "TheExampleMethodVariadic", mockedService.onMethodName) + assert.Equal(t, []int{1, 2, 3}, mockedService.onMethodArguments[0]) + + assert.NotPanics(t, func() { + mockedService.TheExampleMethodVariadic(1, 2, 3) + }) + assert.Panics(t, func() { + mockedService.TheExampleMethodVariadic(1, 2) + }) + +} + +func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}).Return(nil), &mockedService.Mock) + assert.Equal(t, "TheExampleMethodVariadicInterface", mockedService.onMethodName) + assert.Equal(t, []interface{}{1, 2, 3}, mockedService.onMethodArguments[0]) + + assert.NotPanics(t, func() { + mockedService.TheExampleMethodVariadicInterface(1, 2, 3) + }) + assert.Panics(t, func() { + mockedService.TheExampleMethodVariadicInterface(1, 2) + }) + +} + +func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + var expected []interface{} + assert.Equal(t, mockedService.On("TheExampleMethodVariadicInterface", expected).Return(nil), &mockedService.Mock) + assert.Equal(t, "TheExampleMethodVariadicInterface", mockedService.onMethodName) + assert.Equal(t, expected, mockedService.onMethodArguments[0]) + + assert.NotPanics(t, func() { + mockedService.TheExampleMethodVariadicInterface() + }) + assert.Panics(t, func() { + mockedService.TheExampleMethodVariadicInterface(1, 2) + }) + +} + +func Test_Mock_On_WithFuncPanics(t *testing.T) { + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Panics(t, func() { + mockedService.On("TheExampleMethodFunc", func(string) error { return nil }) + }) +} + +func Test_Mock_On_WithFuncTypeArg(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")).Return(nil), &mockedService.Mock) + assert.Equal(t, "TheExampleMethodFuncType", mockedService.onMethodName) + assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), mockedService.onMethodArguments[0]) + + fn := func(string) error { return nil } + mockedService.TheExampleMethodFuncType(fn) + +} + func Test_Mock_Return(t *testing.T) { // make a test impl object @@ -95,11 +212,93 @@ func Test_Mock_Return(t *testing.T) { assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 0, call.Repeatability) + assert.Nil(t, call.WaitFor) } } +func Test_Mock_Return_WaitUntil(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + ch := time.After(time.Second) + + assert.Equal(t, mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).WaitUntil(ch), &mockedService.Mock) + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) { + call := mockedService.Mock.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 1, call.ReturnArguments[0]) + assert.Equal(t, "two", call.ReturnArguments[1]) + assert.Equal(t, true, call.ReturnArguments[2]) + assert.Equal(t, 0, call.Repeatability) + assert.Equal(t, ch, call.WaitFor) + + } + +} + +func Test_Mock_Return_After(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).After(time.Second), &mockedService.Mock) + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) { + call := mockedService.Mock.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 1, call.ReturnArguments[0]) + assert.Equal(t, "two", call.ReturnArguments[1]) + assert.Equal(t, true, call.ReturnArguments[2]) + assert.Equal(t, 0, call.Repeatability) + assert.NotEqual(t, nil, call.WaitFor) + + } + +} + +func Test_Mock_Return_Run(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.Mock.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Run(func(args Arguments) { + arg := args.Get(0).(*ExampleType) + arg.ran = true + }), &mockedService.Mock) + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) { + call := mockedService.Mock.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod3", call.Method) + assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0]) + assert.Equal(t, nil, call.ReturnArguments[0]) + assert.Equal(t, 0, call.Repeatability) + assert.NotEqual(t, nil, call.WaitFor) + assert.NotNil(t, call.Run) + + } + + et := ExampleType{} + assert.Equal(t, false, et.ran) + mockedService.TheExampleMethod3(&et) + assert.Equal(t, true, et.ran) + +} + func Test_Mock_Return_Once(t *testing.T) { // make a test impl object @@ -119,6 +318,7 @@ func Test_Mock_Return_Once(t *testing.T) { assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 1, call.Repeatability) + assert.Nil(t, call.WaitFor) } @@ -143,6 +343,7 @@ func Test_Mock_Return_Twice(t *testing.T) { assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 2, call.Repeatability) + assert.Nil(t, call.WaitFor) } @@ -167,6 +368,7 @@ func Test_Mock_Return_Times(t *testing.T) { assert.Equal(t, "two", call.ReturnArguments[1]) assert.Equal(t, true, call.ReturnArguments[2]) assert.Equal(t, 5, call.Repeatability) + assert.Nil(t, call.WaitFor) } @@ -274,6 +476,43 @@ func Test_Mock_Called(t *testing.T) { } +func asyncCall(m *Mock, ch chan Arguments) { + ch <- m.Called(1, 2, 3) +} + +func Test_Mock_Called_blocks(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond) + + ch := make(chan Arguments) + + go asyncCall(&mockedService.Mock, ch) + + select { + case <-ch: + t.Fatal("should have waited") + case <-time.After(1 * time.Millisecond): + } + + returnArguments := <-ch + + if assert.Equal(t, 1, len(mockedService.Mock.Calls)) { + assert.Equal(t, "asyncCall", mockedService.Mock.Calls[0].Method) + assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0]) + assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1]) + assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2]) + } + + if assert.Equal(t, 3, len(returnArguments)) { + assert.Equal(t, 5, returnArguments[0]) + assert.Equal(t, "6", returnArguments[1]) + assert.Equal(t, true, returnArguments[2]) + } + +} + func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) { var mockedService *TestExampleImplementation = new(TestExampleImplementation) diff --git a/pkg/kubelet/image_manager_test.go b/pkg/kubelet/image_manager_test.go index ffc507e13a5..1b5b30089ad 100644 --- a/pkg/kubelet/image_manager_test.go +++ b/pkg/kubelet/image_manager_test.go @@ -216,7 +216,7 @@ func TestFreeSpaceImagesInUseContainersAreIgnored(t *testing.T) { spaceFreed, err := manager.freeSpace(2048) assert := assert.New(t) require.NoError(t, err) - assert.Equal(1024, spaceFreed) + assert.EqualValues(1024, spaceFreed) assert.Len(fakeDocker.RemovedImages, 1) assert.True(fakeDocker.RemovedImages.Has(imageName(0))) } @@ -245,7 +245,7 @@ func TestFreeSpaceRemoveByLeastRecentlyUsed(t *testing.T) { spaceFreed, err := manager.freeSpace(1024) assert := assert.New(t) require.NoError(t, err) - assert.Equal(1024, spaceFreed) + assert.EqualValues(1024, spaceFreed) assert.Len(fakeDocker.RemovedImages, 1) assert.True(fakeDocker.RemovedImages.Has(imageName(0))) } @@ -277,7 +277,7 @@ func TestFreeSpaceTiesBrokenByDetectedTime(t *testing.T) { spaceFreed, err := manager.freeSpace(1024) assert := assert.New(t) require.NoError(t, err) - assert.Equal(1024, spaceFreed) + assert.EqualValues(1024, spaceFreed) assert.Len(fakeDocker.RemovedImages, 1) assert.True(fakeDocker.RemovedImages.Has(imageName(0))) } @@ -302,7 +302,7 @@ func TestFreeSpaceImagesAlsoDoesLookupByRepoTags(t *testing.T) { spaceFreed, err := manager.freeSpace(1024) assert := assert.New(t) require.NoError(t, err) - assert.Equal(1024, spaceFreed) + assert.EqualValues(1024, spaceFreed) assert.Len(fakeDocker.RemovedImages, 1) assert.True(fakeDocker.RemovedImages.Has(imageName(0))) }