summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkosak@google.com <kosak@google.com@8415998a-534a-0410-bf83-d39667b30386>2015-02-14 02:45:40 +0000
committerkosak@google.com <kosak@google.com@8415998a-534a-0410-bf83-d39667b30386>2015-02-14 02:45:40 +0000
commit6eb9d94884f217d84bcef9054818bd38aeab9d41 (patch)
tree0a6fec800c358fc833a48d1f1bb1b4a4cf0c1725
parent7e2b466b8ccad5bfea1dd6cfa7eb9369175c4247 (diff)
downloadgooglemock-6eb9d94884f217d84bcef9054818bd38aeab9d41.tar.gz
In C++11 and above, makes a mock method whose return type is default
constructible return a default-constructed value by default. git-svn-id: http://googlemock.googlecode.com/svn/trunk@513 8415998a-534a-0410-bf83-d39667b30386
-rw-r--r--include/gmock/gmock-actions.h57
-rw-r--r--test/gmock-actions_test.cc128
-rw-r--r--test/gmock-spec-builders_test.cc22
-rw-r--r--test/gmock_ex_test.cc15
4 files changed, 150 insertions, 72 deletions
diff --git a/include/gmock/gmock-actions.h b/include/gmock/gmock-actions.h
index 46b7bf9..c09c4d6 100644
--- a/include/gmock/gmock-actions.h
+++ b/include/gmock/gmock-actions.h
@@ -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>
diff --git a/test/gmock-actions_test.cc b/test/gmock-actions_test.cc
index a055194..a665fc5 100644
--- a/test/gmock-actions_test.cc
+++ b/test/gmock-actions_test.cc
@@ -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() const { return value_; }
- int 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);
}
diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc
index ae81149..b8f7a11 100644
--- a/test/gmock-spec-builders_test.cc
+++ b/test/gmock-spec-builders_test.cc
@@ -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
}
diff --git a/test/gmock_ex_test.cc b/test/gmock_ex_test.cc
index a5a8a42..3afed86 100644
--- a/test/gmock_ex_test.cc
+++ b/test/gmock_ex_test.cc
@@ -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 "