From 7123d831328321e854b78047effe7a57192a764f Mon Sep 17 00:00:00 2001
From: kosak <kosak@google.com>
Date: Mon, 17 Nov 2014 02:04:46 +0000
Subject: [PATCH] Fix gmock Action behaviour when return type is Wrapper

---
 include/gmock/gmock-actions.h |  8 ++++++--
 test/gmock-actions_test.cc    | 20 ++++++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/include/gmock/gmock-actions.h b/include/gmock/gmock-actions.h
index de502048..f92e479f 100644
--- a/include/gmock/gmock-actions.h
+++ b/include/gmock/gmock-actions.h
@@ -534,16 +534,20 @@ class ReturnAction {
     // Result without considering explicit constructors, thus resolving the
     // ambiguity. value_ is then initialized using its copy constructor.
     explicit Impl(const linked_ptr<R>& value)
-        : value_(ImplicitCast_<Result>(*value)) {}
+        : value_before_cast_(*value),
+          value_(ImplicitCast_<Result>(value_before_cast_)) {}
 
     virtual Result Perform(const ArgumentTuple&) { return value_; }
 
    private:
     GTEST_COMPILE_ASSERT_(!is_reference<Result>::value,
                           Result_cannot_be_a_reference_type);
+    // We save the value before casting just in case it is being cast to a
+    // wrapper type.
+    R value_before_cast_;
     Result value_;
 
-    GTEST_DISALLOW_ASSIGN_(Impl);
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl);
   };
 
   // Partially specialize for ByMoveWrapper. This version of ReturnAction will
diff --git a/test/gmock-actions_test.cc b/test/gmock-actions_test.cc
index 28b48f16..8089a81d 100644
--- a/test/gmock-actions_test.cc
+++ b/test/gmock-actions_test.cc
@@ -509,6 +509,26 @@ TEST(ReturnTest, AcceptsStringLiteral) {
   EXPECT_EQ("world", a2.Perform(make_tuple()));
 }
 
+// Test struct which wraps a vector of integers. Used in
+// 'SupportsWrapperReturnType' test.
+struct IntegerVectorWrapper {
+  std::vector<int> * v;
+  IntegerVectorWrapper(std::vector<int>& _v) : v(&_v) {}  // NOLINT
+};
+
+// Tests that Return() works when return type is a wrapper type.
+TEST(ReturnTest, SupportsWrapperReturnType) {
+  // Initialize vector of integers.
+  std::vector<int> v;
+  for (int i = 0; i < 5; ++i) v.push_back(i);
+
+  // Return() called with 'v' as argument. The Action will return the same data
+  // as 'v' (copy) but it will be wrapped in an IntegerVectorWrapper.
+  Action<IntegerVectorWrapper()> a = Return(v);
+  const std::vector<int>& result = *(a.Perform(make_tuple()).v);
+  EXPECT_THAT(result, ::testing::ElementsAre(0, 1, 2, 3, 4));
+}
+
 // Tests that Return(v) is covaraint.
 
 struct Base {