Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit

Permalink
Merge pull request #1626 from arjun-1/fix-functional-options-diff-ind…
Browse files Browse the repository at this point in the history
…irect-calls

fix: compare functional option names for indirect calls
  • Loading branch information
brackendawson authored Nov 12, 2024
2 parents 07bac60 + 7d99b2b commit 89cbdd9
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 17 deletions.
58 changes: 41 additions & 17 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -1204,32 +1204,38 @@ type tHelper interface {
func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
expectedOpts := reflect.ValueOf(expected)
actualOpts := reflect.ValueOf(actual)

var expectedFuncs []*runtime.Func
var expectedNames []string
for i := 0; i < expectedOpts.Len(); i++ {
expectedNames = append(expectedNames, funcName(expectedOpts.Index(i).Interface()))
f := runtimeFunc(expectedOpts.Index(i).Interface())
expectedFuncs = append(expectedFuncs, f)
expectedNames = append(expectedNames, funcName(f))
}
var actualFuncs []*runtime.Func
var actualNames []string
for i := 0; i < actualOpts.Len(); i++ {
actualNames = append(actualNames, funcName(actualOpts.Index(i).Interface()))
f := runtimeFunc(actualOpts.Index(i).Interface())
actualFuncs = append(actualFuncs, f)
actualNames = append(actualNames, funcName(f))
}
if !assert.ObjectsAreEqual(expectedNames, actualNames) {

if expectedOpts.Len() != actualOpts.Len() {
expectedFmt = fmt.Sprintf("%v", expectedNames)
actualFmt = fmt.Sprintf("%v", actualNames)
return
}

for i := 0; i < expectedOpts.Len(); i++ {
expectedOpt := expectedOpts.Index(i).Interface()
actualOpt := actualOpts.Index(i).Interface()

expectedFunc := expectedNames[i]
actualFunc := actualNames[i]
if expectedFunc != actualFunc {
expectedFmt = expectedFunc
actualFmt = actualFunc
if !isFuncSame(expectedFuncs[i], actualFuncs[i]) {
expectedFmt = expectedNames[i]
actualFmt = actualNames[i]
return
}

expectedOpt := expectedOpts.Index(i).Interface()
actualOpt := actualOpts.Index(i).Interface()

ot := reflect.TypeOf(expectedOpt)
var expectedValues []reflect.Value
var actualValues []reflect.Value
Expand All @@ -1247,9 +1253,9 @@ func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
reflect.ValueOf(actualOpt).Call(actualValues)

for i := 0; i < ot.NumIn(); i++ {
if !assert.ObjectsAreEqual(expectedValues[i].Interface(), actualValues[i].Interface()) {
expectedFmt = fmt.Sprintf("%s %+v", expectedNames[i], expectedValues[i].Interface())
actualFmt = fmt.Sprintf("%s %+v", expectedNames[i], actualValues[i].Interface())
if expectedArg, actualArg := expectedValues[i].Interface(), actualValues[i].Interface(); !assert.ObjectsAreEqual(expectedArg, actualArg) {
expectedFmt = fmt.Sprintf("%s(%T) -> %#v", expectedNames[i], expectedArg, expectedArg)
actualFmt = fmt.Sprintf("%s(%T) -> %#v", expectedNames[i], actualArg, actualArg)
return
}
}
Expand All @@ -1258,7 +1264,25 @@ func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) {
return "", ""
}

func funcName(opt interface{}) string {
n := runtime.FuncForPC(reflect.ValueOf(opt).Pointer()).Name()
return strings.TrimSuffix(path.Base(n), path.Ext(n))
func runtimeFunc(opt interface{}) *runtime.Func {
return runtime.FuncForPC(reflect.ValueOf(opt).Pointer())
}

func funcName(f *runtime.Func) string {
name := f.Name()
trimmed := strings.TrimSuffix(path.Base(name), path.Ext(name))
splitted := strings.Split(trimmed, ".")

if len(splitted) == 0 {
return trimmed
}

return splitted[len(splitted)-1]
}

func isFuncSame(f1, f2 *runtime.Func) bool {
f1File, f1Loc := f1.FileLine(f1.Entry())
f2File, f2Loc := f2.FileLine(f2.Entry())

return f1File == f2File && f1Loc == f2Loc
}
56 changes: 56 additions & 0 deletions mock/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,22 @@ func OpStr(s string) OptionFn {
o.str = s
}
}

func OpBytes(b []byte) OptionFn {
return func(m *options) {
m.str = string(b)
}
}

func (i *TestExampleImplementation) TheExampleMethodFunctionalOptions(x string, opts ...OptionFn) error {
args := i.Called(x, opts)
return args.Error(0)
}

func TheExampleMethodFunctionalOptionsIndirect(i *TestExampleImplementation) {
i.TheExampleMethodFunctionalOptions("test", OpNum(1), OpStr("foo"))
}

//go:noinline
func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
i.Called(yesorno)
Expand Down Expand Up @@ -1522,6 +1533,51 @@ func Test_Mock_AssertExpectationsFunctionalOptionsType_Empty(t *testing.T) {

}

func Test_Mock_AssertExpectationsFunctionalOptionsType_Indirectly(t *testing.T) {

var mockedService = new(TestExampleImplementation)

mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpNum(1), OpStr("foo"))).Return(nil).Once()

tt := new(testing.T)
assert.False(t, mockedService.AssertExpectations(tt))

// make the call now
TheExampleMethodFunctionalOptionsIndirect(mockedService)

// now assert expectations
assert.True(t, mockedService.AssertExpectations(tt))

}

func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Func(t *testing.T) {

var mockedService = new(TestExampleImplementation)

mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpStr("this"))).Return(nil).Once()

tt := new(testing.T)
assert.False(t, mockedService.AssertExpectations(tt))

assert.Panics(t, func() {
mockedService.TheExampleMethodFunctionalOptions("test", OpBytes([]byte("this")))
})
}

func Test_Mock_AssertExpectationsFunctionalOptionsType_Diff_Arg(t *testing.T) {

var mockedService = new(TestExampleImplementation)

mockedService.On("TheExampleMethodFunctionalOptions", "test", FunctionalOptions(OpStr("this"))).Return(nil).Once()

tt := new(testing.T)
assert.False(t, mockedService.AssertExpectations(tt))

assert.Panics(t, func() {
mockedService.TheExampleMethodFunctionalOptions("test", OpStr("that"))
})
}

func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {

var mockedService = new(TestExampleImplementation)
Expand Down

0 comments on commit 89cbdd9

Please sign in to comment.