In C++11 and above, makes a mock method whose return type is default
constructible return a default-constructed value by default.
This commit is contained in:
parent
02d6479259
commit
d478a1f46d
@ -46,6 +46,10 @@
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
|
||||
#if GTEST_LANG_CXX11 // Defined by gtest-port.h via gmock-port.h.
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace testing {
|
||||
|
||||
// To implement an action Foo, define:
|
||||
@ -62,16 +66,17 @@ namespace internal {
|
||||
template <typename F1, typename F2>
|
||||
class ActionAdaptor;
|
||||
|
||||
// BuiltInDefaultValue<T>::Get() returns the "built-in" default
|
||||
// value for type T, which is NULL when T is a pointer type, 0 when T
|
||||
// is a numeric type, false when T is bool, or "" when T is string or
|
||||
// std::string. For any other type T, this value is undefined and the
|
||||
// function will abort the process.
|
||||
// BuiltInDefaultValueGetter<T, true>::Get() returns a
|
||||
// default-constructed T value. BuiltInDefaultValueGetter<T,
|
||||
// false>::Get() crashes with an error.
|
||||
//
|
||||
// This primary template is used when kDefaultConstructible is true.
|
||||
template <typename T, bool kDefaultConstructible>
|
||||
struct BuiltInDefaultValueGetter {
|
||||
static T Get() { return T(); }
|
||||
};
|
||||
template <typename T>
|
||||
class BuiltInDefaultValue {
|
||||
public:
|
||||
// This function returns true iff type T has a built-in default value.
|
||||
static bool Exists() { return false; }
|
||||
struct BuiltInDefaultValueGetter<T, false> {
|
||||
static T Get() {
|
||||
Assert(false, __FILE__, __LINE__,
|
||||
"Default action undefined for the function return type.");
|
||||
@ -81,6 +86,40 @@ class BuiltInDefaultValue {
|
||||
}
|
||||
};
|
||||
|
||||
// BuiltInDefaultValue<T>::Get() returns the "built-in" default value
|
||||
// for type T, which is NULL when T is a raw pointer type, 0 when T is
|
||||
// a numeric type, false when T is bool, or "" when T is string or
|
||||
// std::string. In addition, in C++11 and above, it turns a
|
||||
// default-constructed T value if T is default constructible. For any
|
||||
// other type T, the built-in default T value is undefined, and the
|
||||
// function will abort the process.
|
||||
template <typename T>
|
||||
class BuiltInDefaultValue {
|
||||
public:
|
||||
#if GTEST_LANG_CXX11
|
||||
// This function returns true iff type T has a built-in default value.
|
||||
static bool Exists() {
|
||||
return ::std::is_default_constructible<T>::value;
|
||||
}
|
||||
|
||||
static T Get() {
|
||||
return BuiltInDefaultValueGetter<
|
||||
T, ::std::is_default_constructible<T>::value>::Get();
|
||||
}
|
||||
|
||||
#else // GTEST_LANG_CXX11
|
||||
// This function returns true iff type T has a built-in default value.
|
||||
static bool Exists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static T Get() {
|
||||
return BuiltInDefaultValueGetter<T, false>::Get();
|
||||
}
|
||||
|
||||
#endif // GTEST_LANG_CXX11
|
||||
};
|
||||
|
||||
// This partial specialization says that we use the same built-in
|
||||
// default value for T and const T.
|
||||
template <typename T>
|
||||
|
@ -45,15 +45,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using testing::get;
|
||||
using testing::make_tuple;
|
||||
using testing::tuple;
|
||||
using testing::tuple_element;
|
||||
using testing::internal::BuiltInDefaultValue;
|
||||
using testing::internal::Int64;
|
||||
using testing::internal::UInt64;
|
||||
// This list should be kept sorted.
|
||||
using testing::_;
|
||||
using testing::Action;
|
||||
using testing::ActionInterface;
|
||||
using testing::Assign;
|
||||
@ -73,6 +65,14 @@ using testing::ReturnRef;
|
||||
using testing::ReturnRefOfCopy;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgumentPointee;
|
||||
using testing::_;
|
||||
using testing::get;
|
||||
using testing::internal::BuiltInDefaultValue;
|
||||
using testing::internal::Int64;
|
||||
using testing::internal::UInt64;
|
||||
using testing::make_tuple;
|
||||
using testing::tuple;
|
||||
using testing::tuple_element;
|
||||
|
||||
#if !GTEST_OS_WINDOWS_MOBILE
|
||||
using testing::SetErrnoAndReturn;
|
||||
@ -191,16 +191,43 @@ TEST(BuiltInDefaultValueTest, WorksForConstTypes) {
|
||||
EXPECT_FALSE(BuiltInDefaultValue<const bool>::Get());
|
||||
}
|
||||
|
||||
// Tests that BuiltInDefaultValue<T>::Get() aborts the program with
|
||||
// the correct error message when T is a user-defined type.
|
||||
struct UserType {
|
||||
UserType() : value(0) {}
|
||||
// A type that's default constructible.
|
||||
class MyDefaultConstructible {
|
||||
public:
|
||||
MyDefaultConstructible() : value_(42) {}
|
||||
|
||||
int value;
|
||||
int value() const { return value_; }
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
TEST(BuiltInDefaultValueTest, UserTypeHasNoDefault) {
|
||||
EXPECT_FALSE(BuiltInDefaultValue<UserType>::Exists());
|
||||
// A type that's not default constructible.
|
||||
class MyNonDefaultConstructible {
|
||||
public:
|
||||
// Does not have a default ctor.
|
||||
explicit MyNonDefaultConstructible(int a_value) : value_(a_value) {}
|
||||
|
||||
int value() const { return value_; }
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
#if GTEST_LANG_CXX11
|
||||
|
||||
TEST(BuiltInDefaultValueTest, ExistsForDefaultConstructibleType) {
|
||||
EXPECT_TRUE(BuiltInDefaultValue<MyDefaultConstructible>::Exists());
|
||||
}
|
||||
|
||||
TEST(BuiltInDefaultValueTest, IsDefaultConstructedForDefaultConstructibleType) {
|
||||
EXPECT_EQ(42, BuiltInDefaultValue<MyDefaultConstructible>::Get().value());
|
||||
}
|
||||
|
||||
#endif // GTEST_LANG_CXX11
|
||||
|
||||
TEST(BuiltInDefaultValueTest, DoesNotExistForNonDefaultConstructibleType) {
|
||||
EXPECT_FALSE(BuiltInDefaultValue<MyNonDefaultConstructible>::Exists());
|
||||
}
|
||||
|
||||
// Tests that BuiltInDefaultValue<T&>::Get() aborts the program.
|
||||
@ -213,40 +240,42 @@ TEST(BuiltInDefaultValueDeathTest, IsUndefinedForReferences) {
|
||||
}, "");
|
||||
}
|
||||
|
||||
TEST(BuiltInDefaultValueDeathTest, IsUndefinedForUserTypes) {
|
||||
TEST(BuiltInDefaultValueDeathTest, IsUndefinedForNonDefaultConstructibleType) {
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
BuiltInDefaultValue<UserType>::Get();
|
||||
BuiltInDefaultValue<MyNonDefaultConstructible>::Get();
|
||||
}, "");
|
||||
}
|
||||
|
||||
// Tests that DefaultValue<T>::IsSet() is false initially.
|
||||
TEST(DefaultValueTest, IsInitiallyUnset) {
|
||||
EXPECT_FALSE(DefaultValue<int>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<const UserType>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<MyDefaultConstructible>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::IsSet());
|
||||
}
|
||||
|
||||
// Tests that DefaultValue<T> can be set and then unset.
|
||||
TEST(DefaultValueTest, CanBeSetAndUnset) {
|
||||
EXPECT_TRUE(DefaultValue<int>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<const UserType>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::Exists());
|
||||
|
||||
DefaultValue<int>::Set(1);
|
||||
DefaultValue<const UserType>::Set(UserType());
|
||||
DefaultValue<const MyNonDefaultConstructible>::Set(
|
||||
MyNonDefaultConstructible(42));
|
||||
|
||||
EXPECT_EQ(1, DefaultValue<int>::Get());
|
||||
EXPECT_EQ(0, DefaultValue<const UserType>::Get().value);
|
||||
EXPECT_EQ(42, DefaultValue<const MyNonDefaultConstructible>::Get().value());
|
||||
|
||||
EXPECT_TRUE(DefaultValue<int>::Exists());
|
||||
EXPECT_TRUE(DefaultValue<const UserType>::Exists());
|
||||
EXPECT_TRUE(DefaultValue<const MyNonDefaultConstructible>::Exists());
|
||||
|
||||
DefaultValue<int>::Clear();
|
||||
DefaultValue<const UserType>::Clear();
|
||||
DefaultValue<const MyNonDefaultConstructible>::Clear();
|
||||
|
||||
EXPECT_FALSE(DefaultValue<int>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<const UserType>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::IsSet());
|
||||
|
||||
EXPECT_TRUE(DefaultValue<int>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<const UserType>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<const MyNonDefaultConstructible>::Exists());
|
||||
}
|
||||
|
||||
// Tests that DefaultValue<T>::Get() returns the
|
||||
@ -255,22 +284,20 @@ TEST(DefaultValueTest, CanBeSetAndUnset) {
|
||||
TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
|
||||
EXPECT_FALSE(DefaultValue<int>::IsSet());
|
||||
EXPECT_TRUE(DefaultValue<int>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<UserType>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<UserType>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible>::Exists());
|
||||
|
||||
EXPECT_EQ(0, DefaultValue<int>::Get());
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
DefaultValue<UserType>::Get();
|
||||
DefaultValue<MyNonDefaultConstructible>::Get();
|
||||
}, "");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_UNIQUE_PTR_
|
||||
TEST(DefaultValueDeathTest, GetWorksForMoveOnlyIfSet) {
|
||||
EXPECT_FALSE(DefaultValue<std::unique_ptr<int>>::Exists());
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
DefaultValue<std::unique_ptr<int>>::Get();
|
||||
}, "");
|
||||
TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
|
||||
EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Exists());
|
||||
EXPECT_TRUE(DefaultValue<std::unique_ptr<int>>::Get() == NULL);
|
||||
DefaultValue<std::unique_ptr<int>>::SetFactory([] {
|
||||
return std::unique_ptr<int>(new int(42));
|
||||
});
|
||||
@ -290,36 +317,38 @@ TEST(DefaultValueTest, GetWorksForVoid) {
|
||||
// Tests that DefaultValue<T&>::IsSet() is false initially.
|
||||
TEST(DefaultValueOfReferenceTest, IsInitiallyUnset) {
|
||||
EXPECT_FALSE(DefaultValue<int&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<UserType&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<MyDefaultConstructible&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
|
||||
}
|
||||
|
||||
// Tests that DefaultValue<T&>::Exists is false initiallly.
|
||||
TEST(DefaultValueOfReferenceTest, IsInitiallyNotExisting) {
|
||||
EXPECT_FALSE(DefaultValue<int&>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<UserType&>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<MyDefaultConstructible&>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::Exists());
|
||||
}
|
||||
|
||||
// Tests that DefaultValue<T&> can be set and then unset.
|
||||
TEST(DefaultValueOfReferenceTest, CanBeSetAndUnset) {
|
||||
int n = 1;
|
||||
DefaultValue<const int&>::Set(n);
|
||||
UserType u;
|
||||
DefaultValue<UserType&>::Set(u);
|
||||
MyNonDefaultConstructible x(42);
|
||||
DefaultValue<MyNonDefaultConstructible&>::Set(x);
|
||||
|
||||
EXPECT_TRUE(DefaultValue<const int&>::Exists());
|
||||
EXPECT_TRUE(DefaultValue<UserType&>::Exists());
|
||||
EXPECT_TRUE(DefaultValue<MyNonDefaultConstructible&>::Exists());
|
||||
|
||||
EXPECT_EQ(&n, &(DefaultValue<const int&>::Get()));
|
||||
EXPECT_EQ(&u, &(DefaultValue<UserType&>::Get()));
|
||||
EXPECT_EQ(&x, &(DefaultValue<MyNonDefaultConstructible&>::Get()));
|
||||
|
||||
DefaultValue<const int&>::Clear();
|
||||
DefaultValue<UserType&>::Clear();
|
||||
DefaultValue<MyNonDefaultConstructible&>::Clear();
|
||||
|
||||
EXPECT_FALSE(DefaultValue<const int&>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<UserType&>::Exists());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::Exists());
|
||||
|
||||
EXPECT_FALSE(DefaultValue<const int&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<UserType&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
|
||||
}
|
||||
|
||||
// Tests that DefaultValue<T&>::Get() returns the
|
||||
@ -327,13 +356,13 @@ TEST(DefaultValueOfReferenceTest, CanBeSetAndUnset) {
|
||||
// false.
|
||||
TEST(DefaultValueOfReferenceDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
|
||||
EXPECT_FALSE(DefaultValue<int&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<UserType&>::IsSet());
|
||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
DefaultValue<int&>::Get();
|
||||
}, "");
|
||||
EXPECT_DEATH_IF_SUPPORTED({
|
||||
DefaultValue<UserType>::Get();
|
||||
DefaultValue<MyNonDefaultConstructible>::Get();
|
||||
}, "");
|
||||
}
|
||||
|
||||
@ -661,14 +690,12 @@ TEST(ReturnRefOfCopyTest, IsCovariant) {
|
||||
|
||||
// Tests that DoDefault() does the default action for the mock method.
|
||||
|
||||
class MyClass {};
|
||||
|
||||
class MockClass {
|
||||
public:
|
||||
MockClass() {}
|
||||
|
||||
MOCK_METHOD1(IntFunc, int(bool flag)); // NOLINT
|
||||
MOCK_METHOD0(Foo, MyClass());
|
||||
MOCK_METHOD0(Foo, MyNonDefaultConstructible());
|
||||
#if GTEST_HAS_STD_UNIQUE_PTR_
|
||||
MOCK_METHOD0(MakeUnique, std::unique_ptr<int>());
|
||||
MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>());
|
||||
@ -1160,14 +1187,15 @@ TEST(IgnoreResultTest, MonomorphicAction) {
|
||||
|
||||
// Tests using IgnoreResult() on an action that returns a class type.
|
||||
|
||||
MyClass ReturnMyClass(double /* x */) {
|
||||
MyNonDefaultConstructible ReturnMyNonDefaultConstructible(double /* x */) {
|
||||
g_done = true;
|
||||
return MyClass();
|
||||
return MyNonDefaultConstructible(42);
|
||||
}
|
||||
|
||||
TEST(IgnoreResultTest, ActionReturningClass) {
|
||||
g_done = false;
|
||||
Action<void(int)> a = IgnoreResult(Invoke(ReturnMyClass)); // NOLINT
|
||||
Action<void(int)> a =
|
||||
IgnoreResult(Invoke(ReturnMyNonDefaultConstructible)); // NOLINT
|
||||
a.Perform(make_tuple(2));
|
||||
EXPECT_TRUE(g_done);
|
||||
}
|
||||
|
@ -134,14 +134,21 @@ void PrintTo(const Incomplete& /* x */, ::std::ostream* os) {
|
||||
|
||||
class Result {};
|
||||
|
||||
// A type that's not default constructible.
|
||||
class NonDefaultConstructible {
|
||||
public:
|
||||
explicit NonDefaultConstructible(int /* dummy */) {}
|
||||
};
|
||||
|
||||
class MockA {
|
||||
public:
|
||||
MockA() {}
|
||||
|
||||
MOCK_METHOD1(DoA, void(int n)); // NOLINT
|
||||
MOCK_METHOD1(ReturnResult, Result(int n)); // NOLINT
|
||||
MOCK_METHOD2(Binary, bool(int x, int y)); // NOLINT
|
||||
MOCK_METHOD2(ReturnInt, int(int x, int y)); // NOLINT
|
||||
MOCK_METHOD1(DoA, void(int n));
|
||||
MOCK_METHOD1(ReturnResult, Result(int n));
|
||||
MOCK_METHOD0(ReturnNonDefaultConstructible, NonDefaultConstructible());
|
||||
MOCK_METHOD2(Binary, bool(int x, int y));
|
||||
MOCK_METHOD2(ReturnInt, int(int x, int y));
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockA);
|
||||
@ -1108,15 +1115,16 @@ TEST(UnexpectedCallTest, UnsatisifiedPrerequisites) {
|
||||
b.DoB(4);
|
||||
}
|
||||
|
||||
TEST(UndefinedReturnValueTest, ReturnValueIsMandatory) {
|
||||
TEST(UndefinedReturnValueTest,
|
||||
ReturnValueIsMandatoryWhenNotDefaultConstructible) {
|
||||
MockA a;
|
||||
// TODO(wan@google.com): We should really verify the output message,
|
||||
// but we cannot yet due to that EXPECT_DEATH only captures stderr
|
||||
// while Google Mock logs to stdout.
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
EXPECT_ANY_THROW(a.ReturnResult(1));
|
||||
EXPECT_ANY_THROW(a.ReturnNonDefaultConstructible());
|
||||
#else
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnResult(1), "");
|
||||
EXPECT_DEATH_IF_SUPPORTED(a.ReturnNonDefaultConstructible(), "");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -39,14 +39,17 @@ namespace {
|
||||
using testing::HasSubstr;
|
||||
using testing::internal::GoogleTestFailureException;
|
||||
|
||||
// A user-defined class.
|
||||
class Something {};
|
||||
// A type that cannot be default constructed.
|
||||
class NonDefaultConstructible {
|
||||
public:
|
||||
explicit NonDefaultConstructible(int /* dummy */) {}
|
||||
};
|
||||
|
||||
class MockFoo {
|
||||
public:
|
||||
// A mock method that returns a user-defined type. Google Mock
|
||||
// doesn't know what the default value for this type is.
|
||||
MOCK_METHOD0(GetSomething, Something());
|
||||
MOCK_METHOD0(GetNonDefaultConstructible, NonDefaultConstructible());
|
||||
};
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
@ -59,9 +62,9 @@ TEST(DefaultValueTest, ThrowsRuntimeErrorWhenNoDefaultValue) {
|
||||
// nothing about the return type, it doesn't know what to return,
|
||||
// and has to throw (when exceptions are enabled) or abort
|
||||
// (otherwise).
|
||||
mock.GetSomething();
|
||||
FAIL() << "GetSomething()'s return type has no default value, "
|
||||
<< "so Google Mock should have thrown.";
|
||||
mock.GetNonDefaultConstructible();
|
||||
FAIL() << "GetNonDefaultConstructible()'s return type has no default "
|
||||
<< "value, so Google Mock should have thrown.";
|
||||
} catch (const GoogleTestFailureException& /* unused */) {
|
||||
FAIL() << "Google Test does not try to catch an exception of type "
|
||||
<< "GoogleTestFailureException, which is used for reporting "
|
||||
|
Loading…
x
Reference in New Issue
Block a user