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

Support unique ptr #82

Open
wants to merge 7 commits into
base: cpp11
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion HippoMocks/hippomocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@ class mock : public base_mock
}
template <int X>
void mockedDestructor(int);
void defaultDestructor(int);
};

template <typename T>
struct unique_mock : mock<T>
{
unique_mock(MockRepository *repository);
};

template <class T>
Expand Down Expand Up @@ -779,6 +786,10 @@ class MockRepository {
mock<A> *realMock = (mock<A> *)mck;
realMock->members.emplace_back(new MemberWrap<C>(realRealMember));
}
template <typename Z2>
void SetupDefaultDestructor(Z2 *mck, int x);
template <int X, typename Z2>
int SetupMockedDestructor(Z2 *mck);
template <int X, typename Z2>
TCall<void> &RegisterExpectDestructor(Z2 *mck, RegistrationType expect, const char *fileName, unsigned long lineNo);

Expand Down Expand Up @@ -965,6 +976,10 @@ class MockRepository {
}
template <typename base>
base *Mock();
template <typename base>
std::unique_ptr<base> UniqueMock();
template <typename base, typename D>
std::unique_ptr<base, D> UniqueMock(D deleter);
};

// mock function providers
Expand Down Expand Up @@ -1077,6 +1092,22 @@ void mock<T>::mockedDestructor(int)
isZombie = true;
}

template <typename T>
void mock<T>::defaultDestructor(int)
{
repo->VerifyPartial(this);
isZombie = true;
}

template <typename T>
unique_mock<T>::unique_mock(MockRepository *repository) : mock<T>(repository)
{
// restore function table from mock<T>
*(void **)this = this->funcTables[0];
// setup destructor - since MockRepository is not the owner of the object
this->repo->SetupDefaultDestructor(reinterpret_cast<T*>(this), -1);
}

template <typename Z>
void MockRepository::BasicRegisterExpect(mock<Z> *zMock, int baseOffset, int funcIndex, void (base_mock::*func)(), int X)
{
Expand All @@ -1102,8 +1133,26 @@ void MockRepository::BasicRegisterExpect(mock<Z> *zMock, int baseOffset, int fun
}
}

template <typename Z2>
void MockRepository::SetupDefaultDestructor(Z2 *mck, int X)
{
func_index idx;
((Z2 *)&idx)->~Z2();
int funcIndex = idx.lci * FUNCTION_STRIDE + FUNCTION_BASE;
void (mock<Z2>::*member)(int);
member = &mock<Z2>::defaultDestructor;
BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck),
0, funcIndex,
reinterpret_cast<void (base_mock::*)()>(member), X);
#ifdef EXTRA_DESTRUCTOR
BasicRegisterExpect(reinterpret_cast<mock<Z2> *>(mck),
0, funcIndex+1,
reinterpret_cast<void (base_mock::*)()>(member), X);
#endif
}

template <int X, typename Z2>
TCall<void> &MockRepository::RegisterExpectDestructor(Z2 *mck, RegistrationType expect, const char *fileName, unsigned long lineNo)
int MockRepository::SetupMockedDestructor(Z2 *mck)
{
func_index idx;
((Z2 *)&idx)->~Z2();
Expand All @@ -1118,11 +1167,19 @@ TCall<void> &MockRepository::RegisterExpectDestructor(Z2 *mck, RegistrationType
0, funcIndex+1,
reinterpret_cast<void (base_mock::*)()>(member), X);
#endif
return funcIndex;
}

template <int X, typename Z2>
TCall<void> &MockRepository::RegisterExpectDestructor(Z2 *mck, RegistrationType expect, const char *fileName, unsigned long lineNo)
{
int funcIndex = this->template SetupMockedDestructor<X>(mck);
TCall<void> *call = new TCall<void>(Once, reinterpret_cast<base_mock *>(mck), std::pair<int, int>(0, funcIndex), lineNo, "destructor", fileName);
addCall( call, expect );
return *call;
}


#if defined(_MSC_VER) && !defined(_WIN64)
// Support for COM, see declarations
template <int X, typename Z2, typename Y, typename Z, typename... Args>
Expand Down Expand Up @@ -1227,6 +1284,23 @@ base *MockRepository::Mock() {
return reinterpret_cast<base *>(m);
}

template <typename base>
std::unique_ptr<base> MockRepository::UniqueMock() {
return std::move(std::unique_ptr<base>{reinterpret_cast<base *>(new unique_mock<base>(this))});
}

template <typename base, typename Deleter>
std::unique_ptr<base,Deleter> MockRepository::UniqueMock(Deleter deleter) {
return std::move(std::unique_ptr<base,Deleter>{reinterpret_cast<base *>(new unique_mock<base>(this)), deleter});
}

template<typename base, typename d>
std::unique_ptr<base,d> tee(base*& capture, std::unique_ptr<base,d> && obj) {
capture = obj.get();
return std::move(obj);
}


#include "detail/defaultreporter.h"

#ifndef NO_HIPPOMOCKS_NAMESPACE
Expand Down
1 change: 1 addition & 0 deletions HippoMocksTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set(SOURCES
test_retval.cpp
test_transaction.cpp
test_zombie.cpp
test_unique_ptr.cpp
)

add_executable(HippoMocksTest64
Expand Down
12 changes: 11 additions & 1 deletion HippoMocksTest/HippoMocks.dev
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[Project]
FileName=HippoMocks.dev
Name=HippoMocks
UnitCount=12
UnitCount=13
Type=1
Ver=1
ObjFiles=
Expand Down Expand Up @@ -167,3 +167,13 @@ Priority=1000
OverrideBuildCmd=0
BuildCmd=

[Unit13]
FileName=test_unique_ptr.cpp
CompileCpp=1
Folder=HippoMocks
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=

1 change: 1 addition & 0 deletions HippoMocksTest/HippoMocks.pro
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ SOURCES += \
test_regression_arg_count.cpp \
test_retval.cpp \
test_transaction.cpp \
test_unique_ptr.cpp \
test_zombie.cpp
4 changes: 4 additions & 0 deletions HippoMocksTest/HippoMocksTest.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@
<File
RelativePath=".\test_autoptr.cpp"
>
</File>
<File
RelativePath=".\test_unique_ptr.cpp"
>
</File>
<File
RelativePath=".\test_cfuncs.cpp"
Expand Down
1 change: 1 addition & 0 deletions HippoMocksTest/HippoMocksTest_2012.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
<ClCompile Include="test_com_support_stdcall.cpp" />
<ClCompile Include="test_transaction.cpp" />
<ClCompile Include="test_zombie.cpp" />
<ClCompile Include="test_unique_ptr.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Framework.h" />
Expand Down
2 changes: 1 addition & 1 deletion HippoMocksTest/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ WARNFLAGS = -Wall -Wextra -pedantic -Wno-long-long
CXXOPTS = -I../HippoMocks/ $(WARNFLAGS) -g
TARGET = $(PREFIX)test.exe

OBJECTS = $(patsubst %,$(PREFIX)%,is_virtual.o test.o test_args.o test_array.o test_autoptr.o test_cfuncs.o test_class_args.o test_constref_params.o test_cv_funcs.o test_do.o test_dontcare.o test_dynamic_cast.o test_except.o test_exception_quality.o test_filter.o test_inparam.o test_membermock.o test_mi.o test_nevercall.o test_optional.o test_outparam.o test_overload.o test_ref_args.o test_regression_arg_count.o test_retval.o test_transaction.o test_zombie.o Framework.o main.o)
OBJECTS = $(patsubst %,$(PREFIX)%,is_virtual.o test.o test_args.o test_array.o test_autoptr.o test_cfuncs.o test_class_args.o test_constref_params.o test_cv_funcs.o test_do.o test_dontcare.o test_dynamic_cast.o test_except.o test_exception_quality.o test_filter.o test_inparam.o test_membermock.o test_mi.o test_nevercall.o test_optional.o test_outparam.o test_overload.o test_ref_args.o test_regression_arg_count.o test_retval.o test_transaction.o test_zombie.o test_unique_ptr.o Framework.o main.o)

all: $(TARGETS)

Expand Down
102 changes: 102 additions & 0 deletions HippoMocksTest/test_unique_ptr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include "Framework.h"
#include "hippomocks.h"
#include <string>

class IU {
public:
virtual ~IU() {}
virtual void f() = 0;
virtual void g() {}
virtual int h() { return 0; }
virtual void i(std::string ) {}
virtual void j(std::string ) = 0;
};

TEST (checkUniquePtrDestruction)
{
MockRepository mocks;
auto iu = mocks.UniqueMock<IU>();
}

TEST (checkCallsWorksOnUniquePtr)
{
MockRepository mocks;
std::unique_ptr<IU> iu = mocks.UniqueMock<IU>();
mocks.ExpectCall(iu.get(), IU::f);
iu->f();
}

TEST (checkMissingExpectationsWorksOnUniquePtr)
{
MockRepository mocks;
bool exceptionCaught = false;
std::unique_ptr<IU> iu = mocks.UniqueMock<IU>();
try
{
iu->f();
}
catch (HippoMocks::NotImplementedException const&)
{
exceptionCaught = true;
}
CHECK(exceptionCaught);
}

TEST (checkNeverCallWorksOnUniquePtr)
{
bool exceptionCaught = false;
MockRepository mocks;
auto iu = mocks.UniqueMock<IU>();
Call &callF = mocks.ExpectCall(iu.get(), IU::f);
mocks.OnCall(iu.get(), IU::g);
mocks.NeverCall(iu.get(), IU::g).After(callF);
iu->g();
iu->g();
iu->f();
try
{
iu->g();
}
catch (HippoMocks::ExpectationException &)
{
exceptionCaught = true;
}
CHECK(exceptionCaught);
}

TEST (checkClassArgumentsAcceptedWithUniquePtr)
{
MockRepository mocks;
auto iamock = mocks.UniqueMock<IU>();
mocks.OnCall(iamock.get(), IU::i).With("hi");
mocks.OnCall(iamock.get(), IU::j).With("bye");
iamock->i("hi");
iamock->j("bye");
}

TEST (checkClassArgumentsCheckedWithUniquePtr)
{
MockRepository mocks;
auto iamock = mocks.UniqueMock<IU>();
mocks.OnCall(iamock.get(), IU::i).With("hi");
mocks.OnCall(iamock.get(), IU::j).With("bye");
bool exceptionCaught = false;
try
{
iamock->i("bye");
}
catch (HippoMocks::ExpectationException)
{
exceptionCaught = true;
}
CHECK(exceptionCaught);
mocks.reset();
}

TEST (checkClassArgumentsIgnoredWithUniquePtr)
{
MockRepository mocks;
auto iamock = mocks.UniqueMock<IU>();
mocks.OnCall(iamock.get(), IU::i);
iamock->i("bye");
}