Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocks and std::unique_ptr #10

Closed
ghost opened this issue Jan 22, 2015 · 8 comments
Closed

Mocks and std::unique_ptr #10

ghost opened this issue Jan 22, 2015 · 8 comments

Comments

@ghost
Copy link

ghost commented Jan 22, 2015

How am I supposed to pass a mock as unique pointer?

For example:

class Object
{
public:
    ~Object() {}
    virtual void DoSomething() = 0;
};

class Handler
{
public:
    explicit Handler(std::unique_ptr<Object> SomeObject)
        : m_Object(std::move(SomeObject))
    {
    }

    void Handle()
    {
        m_Object->DoSomething();
    }

private:
    std::unique_ptr<Object> m_Object;
};

TEST()
{
    Mock<Object> ObjectMock;
    When(Method(ObjectMock, DoSomething)).AlwaysReturn();
    Object* SomeObject = &ObjectMock.get();

    Handler SomeHandler(make_unique(SomeObject));
    SomeHandler.Handle();

    Verify(Method(ObjectMock, DoSomething)).Once();
}

This code crashes on exiting the test because both Mock and Handler take ownership of the Object instance. Could you add some release method to Mock which releases ownership but still holds a weak reference to the object? Or is there another way to handle this?

@eranpeer
Copy link
Owner

Hi,
I made some changes trying to make Fakeit support your request, though i had to revert them all back since for some reason it does not work on gcc.
Things get tricky since the instance held by the mock is not a real instance (since the mocked class is abstract). It is a faked instance managed by the mock object. Letting the test/user delete the instance fails because the FakeObject's virtual table does not have a destructor.
I will make another effort in the next few days to make it work (by putting a fake destructor in the correct position of the virtual table) I hope I will be able to make it work.

@eranpeer eranpeer reopened this Jan 22, 2015
@eranpeer
Copy link
Owner

Ok, It works! You can mock the dtor now!
The following code will work:

Mock<SomeInterface> mock;
Fake(Dtor(mock)); // Stub the dtor to do nothing!!
SomeInterface * i = &mock.get();
std::unique_ptr<SomeInterface> ptr(i);

You can do much more than that:

void mock_virtual_dtor_with_when() {
  int a = 0;
  Mock<SomeInterface> mock;
  When(Dtor(mock)).Do([&](){a++; });
  SomeInterface * i = &(mock.get());
  delete i; // a++
  delete i; // a++
  ASSERT_EQUAL(2, a);
}

Enjoy!

@ghost
Copy link
Author

ghost commented Jan 31, 2015

Thanks for your effort! I will certainly try this out next week.

@ghost
Copy link
Author

ghost commented Feb 5, 2015

Hi, it works fine now. I have just a small remark:

At this line GCC 4.8 gives the warning ISO C++ forbids casting between pointer-to-function and pointer-to-object. Is there something we could do to avoid that warning?

@eranpeer
Copy link
Owner

eranpeer commented Feb 5, 2015

Sure, I'll fix it this weekend.
On Feb 5, 2015 9:37 AM, "Stijn Van Nieuwenhuyse" notifications@github.com
wrote:

Hi, it works fine now. I have just a small remark:

At this
https://github.com/eranpeer/FakeIt/blob/master/include/mockutils/gcc/VirtualTable.hpp#L80
line GCC 4.8 gives the warning ISO C++ forbids casting between
pointer-to-function and pointer-to-object. Is there something we could do
to avoid that warning?


Reply to this email directly or view it on GitHub
#10 (comment).

@eranpeer
Copy link
Owner

eranpeer commented Feb 5, 2015

Done! I fixed the gcc warning.

@misery
Copy link
Contributor

misery commented Jul 20, 2015

I have a similar crash here with Qt's QSharedPointer. Used current master branch!

#0 0x685d62 in fakeit::MethodProxyCreator<void>::methodProxy(unsigned int) [..]/external/fakeit.hpp:5815:20
#1 0x685459 in void fakeit::MethodProxyCreator<void>::methodProxyX<0>() [..]/external/fakeit.hpp:5820:20
#2 0x689a89 in fakeit::VirtualTable<ActivationContext>::dtor(int) [..]/external/fakeit.hpp:5615:13
#3 0x7fc23f73049f in QScopedPointerDeleter<ActivationContext>::cleanup(ActivationContext*) [..]/QtCore/qscopedpointer.h:54:9
#4 0x7fc23f730028 in QScopedPointer<ActivationContext, QScopedPointerDeleter<ActivationContext> >::~QScopedPointer() [..]/QtCore/qscopedpointer.h:101:9

The code:

Mock<ActivationContext> context;
When(Dtor(context));

QSharedPointer<AuthModel> model(new AuthModel(&context.get()));

@jessevdp
Copy link

What happens when both the mock and the unique_ptr (that points to the mocked instance) are deleted?

{
Mock<SomeType> mock;
Fake(Dtor(mock));
std::unique_ptr<SomeType> ptr {&mock.get()};
} // <- both are deleted

I'm having some issues and I suspect it has to do with this..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants