fex
fex

Reputation: 307

GMock: How to return a fuction pointer defined by an EXPECT_CALL()

I am using a framework that passes around function pointers as void*. I want a mock to return a function pointer, and I want to define the function in-place (like a lambda; which does not work as shown below).

A minimal working example is shown below.

#include <gtest/gtest.h>
#include <gmock/gmock.h>

using namespace std;
using namespace testing;

class Original
{
public:
    typedef int(*fptr)();

    void Func() 
    {
        void* f = Func2();
        fptr func = reinterpret_cast<fptr>(f);
        if (func) {
            int i = func();
            if (i == 1) {
                //do something
            } else if (i == 3) {
                //NOTE my unit test should test this decision branch
            }
        }
    }

    static int Func3() {return 1;}

    virtual void* Func2() {return (void*)&Func3;}
};

class MyMock : public Original
{
public:
    MOCK_METHOD0(Func2, void*());
};

My main goal: I want to get rid of this function, and define it inline in the EXPECT_CALL(). See below.

int MockFunc() {cout << "mock func" << endl; return 3;}

The test case:

TEST(MYTEST, Test)
{
    MyMock m;

    //WORKS: compiles and works as expected, 
    //but I do not want to use **MockFunc**
    EXPECT_CALL(m, Func2()).Times(AtLeast(1))
        .WillRepeatedly(Return(&MockFunc)); 

    //DOES NOT WORK: Does not compile, of course 
    //(compiler message below this code block)
    EXPECT_CALL(m, Func2()).Times(AtLeast(1))
        .WillRepeatedly(Return((void*)&([](){return 3;}))); 
    m.Func();
}

main.cpp:117:90: error: taking address of temporary [-fpermissive]

For completeness, the main():

int main(int argc, char** argv)
{    
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

So the question again: How can I get rid of the MockFunc() function and define its contents in-place within the Return()?

Upvotes: 3

Views: 3172

Answers (1)

skypjack
skypjack

Reputation: 50540

The following statement should work:

EXPECT_CALL(m, Func2()).Times(AtLeast(1)).WillRepeatedly(Return((void*)(+([](){return 3;}))));

It exploits the fact that non-capturing lambdas decay to function pointers.
In other terms, the resulting type of the expression (+([](){return 3;}) is int(*)(). You can then cast it to void* as you did. The error should disappear as well, for you are no longer getting the address of a temporary.

Upvotes: 6

Related Questions