Skip to content

Commit

Permalink
dnk
Browse files Browse the repository at this point in the history
  • Loading branch information
FranckRJ committed Apr 21, 2024
1 parent 2fbb239 commit ff338c2
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 99 deletions.
6 changes: 5 additions & 1 deletion include/fakeit/StubbingProgress.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ namespace fakeit {

template<typename T>
MethodStubbingProgress<R, arglist...>& ReturnCapture(T&& r) {
auto store = std::make_shared<typename std::remove_reference<R>::type>(std::forward<T>(r));
static_assert(std::is_constructible<
typename std::remove_cv<typename std::remove_reference<R>::type>::type&,
typename std::remove_cv<typename std::remove_reference<T>::type>::type&>::value,
"The type captured by ReturnCapture() (named T) must be compatible with the return type of the function (named R), i.e. T t{...}; R& r = t; must compile without creating temporaries.");
auto store = std::make_shared<typename std::remove_cv<typename std::remove_reference<T>::type>::type>(std::forward<T>(r));
return Do([store](const typename fakeit::test_arg<arglist>::type...) mutable -> R {
return std::forward<R>(*store);
});
Expand Down
254 changes: 156 additions & 98 deletions tests/referece_types_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,29 @@ struct ReferenceTypesTests: tpunit::TestFixture {

class AbstractType {
public:
virtual void foo() = 0;
virtual const std::string& getContent() = 0;

// Return true if object was sliced, false otherwise.
virtual bool wasObjectSliced() {
return true;
}
};

class ConcreteType: public AbstractType {
public:
int state;
ConcreteType(int value = 10) :
state(value) {
std::string content;
ConcreteType(const std::string& newContent = "defaultContent") :
content{newContent} {
}
const std::string& getContent() override {
return content;
}
void foo() override {
bool wasObjectSliced() override {
return false;
}

bool operator==(const ConcreteType& other) const {
return (other.state == this->state);
return (other.content == this->content);
}

};
Expand All @@ -42,21 +51,24 @@ struct ReferenceTypesTests: tpunit::TestFixture {
virtual ConcreteType& returnConcreteTypeByRef() = 0;
virtual const std::string& returnStringByConstRef() = 0;
virtual std::string& returnStringByRef() = 0;
virtual const std::unique_ptr<std::string>& returnMoveOnlyByConstRef() = 0;
virtual std::unique_ptr<std::string>& returnMoveOnlyByRef() = 0;
};

ReferenceTypesTests() :
tpunit::TestFixture(
//
TEST(ReferenceTypesTests::implicitStubbingDefaultReturnValues),
TEST(ReferenceTypesTests::explicitStubbingDefaultReturnValues),
TEST(ReferenceTypesTests::explicitStubbingReturnCopyValuesForRef),
TEST(ReferenceTypesTests::explicitStubbingReturnValuesCopyForRRef),
TEST(ReferenceTypesTests::explicitStubbingReturnValues),
TEST(ReferenceTypesTests::explicitStubbingDefaultReturnValues_with_AlwaysReturn),
TEST(ReferenceTypesTests::explicitStubbingReturnValues_with_AlwaysReturn),
TEST(ReferenceTypesTests::explicitStubbingReturnCopyValuesForRef_with_AlwaysReturn),
TEST(ReferenceTypesTests::explicitStubbingReturnCopyValues_with_AlwaysReturn),
TEST(ReferenceTypesTests::explicitStubbingReturnValues_by_assignment),
TEST(ReferenceTypesTests::explicitStubbingReturnValues)
TEST(ReferenceTypesTests::explicitStubbingReturnCaptureByCopy),
TEST(ReferenceTypesTests::explicitStubbingReturnCaptureByMove),
TEST(ReferenceTypesTests::explicitStubbingReturnCaptureByTemporary),
TEST(ReferenceTypesTests::explicitStubbingReturnCaptureForRef_with_AlwaysReturn),
TEST(ReferenceTypesTests::explicitStubbingReturnCaptureForRValRef_with_AlwaysReturn)
//
) {
}
Expand Down Expand Up @@ -140,66 +152,6 @@ struct ReferenceTypesTests: tpunit::TestFixture {
ASSERT_EQUAL(&c, &i.returnAbstractTypeByRef());
}

void explicitStubbingReturnCopyValuesForRef() {
Mock<ReferenceInterface> mock;

// add scope so we know we are copying
{
std::string a_string{"myString"};
int num{ 1 };

// explicit copy here
When(Method(mock, returnStringByConstRef)).ReturnCapture(a_string);
When(Method(mock, returnIntByRef)).ReturnCapture(num);

// modify now so know whether or not is was copied
a_string = "modified";
num = 2;
}

ReferenceInterface& i = mock.get();

// Fundamental types are initiated to 0.
EXPECT_EQUAL("myString", i.returnStringByConstRef());
EXPECT_EQUAL(1, i.returnIntByRef());
}

void explicitStubbingReturnValuesCopyForRRef() {
Mock<ReferenceInterface> mock;

{
When(Method(mock, returnStringByConstRef)).ReturnCapture(std::string{ "myConstRefString" });
When(Method(mock, returnStringByRef)).ReturnCapture(std::string{ "myRefString" });
When(Method(mock, returnConcreteTypeByRef)).ReturnCapture(ConcreteType(20));
When(Method(mock, returnIntByRef)).ReturnCapture(1);
}

ReferenceInterface& i = mock.get();

EXPECT_EQUAL("myConstRefString", i.returnStringByConstRef());
EXPECT_EQUAL("myRefString", i.returnStringByRef());
EXPECT_EQUAL(ConcreteType(20), i.returnConcreteTypeByRef());
EXPECT_EQUAL(1, i.returnIntByRef());
}

void explicitStubbingReturnCopyValuesForRef_with_AlwaysReturn() {
Mock<ReferenceInterface> mock;

{
When(Method(mock, returnStringByConstRef)).AlwaysReturnCapture(std::string{ "myConstRefString" });
When(Method(mock, returnStringByRef)).AlwaysReturnCapture(std::string{ "myRefString" });
When(Method(mock, returnConcreteTypeByRef)).AlwaysReturnCapture(ConcreteType(20));
When(Method(mock, returnIntByRef)).AlwaysReturnCapture(1);
}

ReferenceInterface& i = mock.get();

EXPECT_EQUAL("myConstRefString", i.returnStringByConstRef());
EXPECT_EQUAL("myRefString", i.returnStringByRef());
EXPECT_EQUAL(ConcreteType(20), i.returnConcreteTypeByRef());
EXPECT_EQUAL(1, i.returnIntByRef());
}

void explicitStubbingReturnValues_with_AlwaysReturn() {
Mock<ReferenceInterface> mock; //

Expand All @@ -224,33 +176,6 @@ struct ReferenceTypesTests: tpunit::TestFixture {
ASSERT_EQUAL(&c, &i.returnAbstractTypeByRef());
}

void explicitStubbingReturnCopyValues_with_AlwaysReturn() {
Mock<ReferenceInterface> mock;

// add scope so we know we are copying
{
std::string a_string{ "myString" };
int num{ 1 };

// explicit copy here
When(Method(mock, returnStringByConstRef)).AlwaysReturnCapture(a_string);
When(Method(mock, returnIntByRef)).AlwaysReturnCapture(num);

// modify now so know whether or not is was copied
a_string = "modified";
num = 2;
}

ReferenceInterface& i = mock.get();

// Fundamental types are initiated to 0.
EXPECT_EQUAL("myString", i.returnStringByConstRef());
EXPECT_EQUAL("myString", i.returnStringByConstRef());

EXPECT_EQUAL(1, i.returnIntByRef());
EXPECT_EQUAL(1, i.returnIntByRef());
}

void explicitStubbingReturnValues_by_assignment() {
Mock<ReferenceInterface> mock; //

Expand Down Expand Up @@ -299,4 +224,137 @@ struct ReferenceTypesTests: tpunit::TestFixture {
#endif
}

void explicitStubbingReturnCaptureByCopy() {
Mock<ReferenceInterface> mock;

// add scope so we know we are copying
{
std::string aString{"myString"};
int num = 1;
ConcreteType concrete{"myConcreteType"};

// explicit copy here
When(Method(mock, returnStringByConstRef)).ReturnCapture(aString);
When(Method(mock, returnIntByRef)).ReturnCapture(num);
When(Method(mock, returnAbstractTypeByRef)).ReturnCapture(concrete);

// modify now so know whether or not is was copied
aString = "modified";
num = 2;
concrete.content = "modified";
}

ReferenceInterface& i = mock.get();

EXPECT_EQUAL("myString", i.returnStringByConstRef());
EXPECT_EQUAL(1, i.returnIntByRef());
AbstractType& abstract = i.returnAbstractTypeByRef();
EXPECT_FALSE(abstract.wasObjectSliced());
EXPECT_EQUAL("myConcreteType", abstract.getContent());
}

void explicitStubbingReturnCaptureByMove() {
Mock<ReferenceInterface> mock;

// add scope so we know we are moving
{
std::string aString{"aString"};
std::string bString{"bString"};
std::unique_ptr<std::string> aPtrString{new std::string{"aPtrString"}};
std::unique_ptr<std::string> bPtrString{new std::string{"bPtrString"}};
ConcreteType concrete{"myConcreteType"};

// explicit move here
When(Method(mock, returnStringByConstRef)).ReturnCapture(std::move(aString));
When(Method(mock, returnStringByRef)).ReturnCapture(std::move(bString));
When(Method(mock, returnMoveOnlyByConstRef)).ReturnCapture(std::move(aPtrString));
When(Method(mock, returnMoveOnlyByRef)).ReturnCapture(std::move(bPtrString));
When(Method(mock, returnAbstractTypeByRef)).ReturnCapture(std::move(concrete));

// Verify objects were moved.
EXPECT_TRUE(aString.empty());
EXPECT_TRUE(bString.empty());
EXPECT_EQUAL(aPtrString, nullptr);
EXPECT_EQUAL(bPtrString, nullptr);
EXPECT_TRUE(concrete.content.empty());
}

ReferenceInterface& i = mock.get();

EXPECT_EQUAL("aString", i.returnStringByConstRef());
EXPECT_EQUAL("bString", i.returnStringByRef());
EXPECT_EQUAL("aPtrString", *i.returnMoveOnlyByConstRef());
EXPECT_EQUAL("bPtrString", *i.returnMoveOnlyByRef());
AbstractType& abstract = i.returnAbstractTypeByRef();
EXPECT_FALSE(abstract.wasObjectSliced());
EXPECT_EQUAL("myConcreteType", abstract.getContent());
}

void explicitStubbingReturnCaptureByTemporary() {
Mock<ReferenceInterface> mock;

{
When(Method(mock, returnStringByConstRef)).ReturnCapture(std::string{"aString"});
When(Method(mock, returnStringByRef)).ReturnCapture(std::string{"bString"});
When(Method(mock, returnMoveOnlyByConstRef)).ReturnCapture(std::unique_ptr<std::string>(new std::string{"aPtrString"}));
When(Method(mock, returnMoveOnlyByRef)).ReturnCapture(std::unique_ptr<std::string>(new std::string{"bPtrString"}));
When(Method(mock, returnAbstractTypeByRef)).ReturnCapture(ConcreteType{"myConcreteType"});
}

ReferenceInterface& i = mock.get();

EXPECT_EQUAL("aString", i.returnStringByConstRef());
EXPECT_EQUAL("bString", i.returnStringByRef());
EXPECT_EQUAL("aPtrString", *i.returnMoveOnlyByConstRef());
EXPECT_EQUAL("bPtrString", *i.returnMoveOnlyByRef());
AbstractType& abstract = i.returnAbstractTypeByRef();
EXPECT_FALSE(abstract.wasObjectSliced());
EXPECT_EQUAL("myConcreteType", abstract.getContent());
}

void explicitStubbingReturnCaptureForRef_with_AlwaysReturn() {
Mock<ReferenceInterface> mock;

// add scope so we know we are copying
{
std::string a_string{ "myString" };
int num{ 1 };

// explicit copy here
When(Method(mock, returnStringByConstRef)).AlwaysReturnCapture(a_string);
When(Method(mock, returnIntByRef)).AlwaysReturnCapture(num);

// modify now so know whether or not is was copied
a_string = "modified";
num = 2;
}

ReferenceInterface& i = mock.get();

// Fundamental types are initiated to 0.
EXPECT_EQUAL("myString", i.returnStringByConstRef());
EXPECT_EQUAL("myString", i.returnStringByConstRef());

EXPECT_EQUAL(1, i.returnIntByRef());
EXPECT_EQUAL(1, i.returnIntByRef());
}

void explicitStubbingReturnCaptureForRValRef_with_AlwaysReturn() {
Mock<ReferenceInterface> mock;

{
When(Method(mock, returnStringByConstRef)).AlwaysReturnCapture(std::string{ "myConstRefString" });
When(Method(mock, returnStringByRef)).AlwaysReturnCapture(std::string{ "myRefString" });
When(Method(mock, returnConcreteTypeByRef)).AlwaysReturnCapture(ConcreteType("myConcreteType"));
When(Method(mock, returnIntByRef)).AlwaysReturnCapture(1);
}

ReferenceInterface& i = mock.get();

EXPECT_EQUAL("myConstRefString", i.returnStringByConstRef());
EXPECT_EQUAL("myRefString", i.returnStringByRef());
EXPECT_EQUAL(ConcreteType("myConcreteType"), i.returnConcreteTypeByRef());
EXPECT_EQUAL(1, i.returnIntByRef());
}

} __ReferenceTypesTests;

0 comments on commit ff338c2

Please sign in to comment.