google / google/googletest

[Bug]: Cannot mock recursive lambda with deducing this parameter

Open
#4,549 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
39.5k
Forks
10.9k
Avg merge
6d 13h
Merged PRs (30d)
1

Description

### Describe the issue

Using `MockFunction` to mock a lambda function with deducing this self parameter gives a compile error with gcc 14.1 on Ubuntu 24.04
```
test.cpp: In member function ‘virtual void ::testing::Expr_test_1002_Test::TestBody()’:
test.cpp:975:20: error: ‘auto’ parameter not permitted in this context
975 | MockFunction mockNegVisit;
| ^~~~~~~~~~~~~~~~
test.cpp:975:20: error: a function type cannot have an explicit object parameter
test.cpp:975:20: note: the type of an explicit object member function is a regular function type
In file included from googletest/googlemock/include/gmock/gmock-function-mocker.h:43,
from googletest/googlemock/include/gmock/gmock.h:58,
from test.cpp:14:
googletest/googlemock/include/gmock/gmock-spec-builders.h: In instantiation of ‘class testing::MockFunction’:
test.cpp:975:44: required from here
test.cpp:975:20: note: 975 | MockFunction mockNegVisit;
test.cpp:975:20: note: | ^~~~~~~~~~~~
googletest/googlemock/include/gmock/gmock-spec-builders.h:2033:7: error: invalid use of incomplete type ‘struct testing::internal::SignatureOf’
2033 | class MockFunction : public internal::MockFunction> {
| ^~~~~~~~~~~~
googletest/googlemock/include/gmock/gmock-spec-builders.h:1955:8: note: declaration of ‘struct testing::internal::SignatureOf’
1955 | struct SignatureOf;
| ^~~~~~~~~~~
googletest/googlemock/include/gmock/gmock-spec-builders.h:2034:9: error: invalid use of incomplete type ‘struct testing::internal::SignatureOf’
2034 | using Base = internal::MockFunction>;
| ^~~~
googletest/googlemock/include/gmock/gmock-spec-builders.h:1955:8: note: declaration of ‘struct testing::internal::SignatureOf’
1955 | struct SignatureOf;
| ^~~~~~~~~~~
test.cpp: In lambda function:
test.cpp:983:20: error: ‘class testing::MockFunction’ has no member named ‘AsStdFunction’
983 | mockNegVisit.AsStdFunction(),
```

The code defines a recursive variant with visit lambda overloads
```
namespace {
struct Expr;
struct Neg {
shared_ptr expr;
};
struct Add {
shared_ptr lhs, rhs;
};
struct Mul {
shared_ptr lhs, rhs;
};
struct Expr: variant {
using variant::variant;
};

auto intVisit = [](int i) -> int { return i; };
auto negVisit = [](this const auto& self, const Neg& n) -> int { return -visit(self, *n.expr); };
auto addVisit = [](this const auto& self, const Add& a) -> int { return visit(self, *a.lhs) + visit(self, *a.rhs); };
auto mulVisit = [](this const auto& self, const Mul& m) -> int { return visit(self, *m.lhs) * visit(self, *m.rhs); };

template
struct overload: Ts... { using Ts::operator()...; };

auto evalExpr(const Expr& expr) -> int {
return visit(overload{
intVisit,
negVisit,
addVisit,
mulVisit,
},
expr);
}
}
```
test_1001 works
```
TEST(Expr, test_1001) {
// 5 + 2 = 7
EXPECT_EQ(evalExpr(Add{make_shared(5), make_shared(2)}), 7);
}
```
test_1002 fails to compile `mockNegVisit` though `mockIntVisit` without the auto self parameter works
```
TEST(Expr, test_1002) {
// 5 + 2 = 7
Add a{make_shared(5), make_shared(2)};

MockFunction mockIntVisit;
MockFunction mockNegVisit;

ON_CALL(mockIntVisit, Call).WillByDefault(ReturnArg<0>());

auto evalExprMock = [&mockIntVisit, &mockNegVisit](const Expr& expr) -> int {
return visit(overload{
mockIntVisit.AsStdFunction(),
mockNegVisit.AsStdFunction(),
addVisit,
mulVisit,
},
expr);
};
auto result = evalExprMock(a);
EXPECT_EQ(result, 7);
}
```

Is there a way to mock a recursive lambda?

### Steps to reproduce the problem

As above

### What version of GoogleTest are you using?

latest main branch of GoogleTest repo

### What operating system and version are you using?

Ubuntu 24.04

### What compiler and version are you using?

GCC 14.1

### What build system are you using?

CMake 3.29.3

### Additional context

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with the reproducer in the issue using GCC 14.1, then inspect MockFunction, SignatureOf, and AsStdFunction in googletest/googlemock/include/gmock/gmock-spec-builders.h. Compare the failing explicit-object-parameter signature with the working MockFunction case. Done means an agreed way for MockFunction to handle recursive lambdas, backed by a regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
cmake, cpp
Domain
testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.