OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef REMOTING_HOST_MOCK_CALLBACK_H_ | 5 #ifndef REMOTING_HOST_MOCK_CALLBACK_H_ |
6 #define REMOTING_HOST_MOCK_CALLBACK_H_ | 6 #define REMOTING_HOST_MOCK_CALLBACK_H_ |
7 | 7 |
8 // TODO(lukasza): If possible, move this header file to base/mock_callback.h | 8 // TODO(lukasza): If possible, move this header file to base/mock_callback.h |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/callback.h" | 12 #include "base/callback.h" |
13 #include "base/memory/ref_counted.h" | |
13 | 14 |
14 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
15 | 16 |
16 namespace remoting { | 17 namespace remoting { |
17 | 18 |
19 // MockCallback<Sig> can be used to mock Callback<Sig> from base/callback.h | |
Lambros
2014/12/03 03:20:25
This basically looks fine, though I can't say I fu
| |
20 // | |
21 // Basic usage example: | |
22 // | |
23 // MockCallback<void(int)> mock_callback; | |
24 // EXPECT_CALL(mock_callback, Run(123)).Times(2); | |
25 // base::Callback<void(int)> callback = mock_callback.GetCallback(); | |
26 // | |
27 // // Use |callback| in the remainder of the test. | |
28 // // GMock will enforce the expectations from above. | |
29 // | |
30 // HasRemainingCallbacks usage example: | |
31 // | |
32 // MockCallback<int()> mock_callback; | |
33 // EXPECT_CALL(mock_callback, Run()).WillOnce(Return(123)); | |
34 // HypotheticalFunctionUnderTest(mock_callback.GetCallback()); | |
35 // EXPECT_FALSE(mock_callback.HasRemainingCallbacks()) | |
36 // << "Verify that FunctionUnderTest didn't store the callback " | |
Lambros
2014/12/03 03:20:25
This feels like it should be a code comment, not a
Łukasz Anforowicz
2014/12/03 17:54:22
Maybe. I think that having this message in the ou
| |
37 // << "and therefore callers of FunctionUnderTest don't have to " | |
38 // << "worry about lifetime of arguments bound to the callback"; | |
39 | |
18 template <typename Sig> | 40 template <typename Sig> |
19 class MockCallback; | 41 class MockCallback; |
20 | 42 |
21 template <typename R> | 43 template <typename R> |
22 class MockCallback<R()> { | 44 class MockCallback<R()> { |
23 public: | 45 public: |
24 MOCK_CONST_METHOD0_T(Run, R()); | 46 MOCK_CONST_METHOD0_T(Run, R()); |
25 | 47 |
26 MockCallback() { | 48 MockCallback() : mock_callback_tracker_(new MockCallbackTracker(this)) { |
27 } | 49 } |
28 | 50 |
29 // Caller of GetCallback has to guarantee that the returned callback | 51 // Caller of GetCallback has to guarantee that the returned callback |
30 // will not be run after |this| is destroyed. | 52 // will not be run after |this| is destroyed. |
31 base::Callback<R()> GetCallback() { | 53 base::Callback<R()> GetCallback() { |
32 return base::Bind(&MockCallback<R()>::Run, base::Unretained(this)); | 54 return base::Bind(&MockCallbackTracker::Run, mock_callback_tracker_); |
55 } | |
56 | |
57 // Returns |true| if callbacks returned by |GetCallback| have not been | |
58 // destroyed yet. | |
59 bool HasRemainingCallbacks() const { | |
60 bool is_tracker_field_the_only_ref = mock_callback_tracker_->HasOneRef(); | |
61 return !is_tracker_field_the_only_ref; | |
33 } | 62 } |
34 | 63 |
35 private: | 64 private: |
65 // MockCallbackTracker has 2 goals: | |
66 // - Enable counting of callbacks for |HasRemainingCallbacks| method. | |
67 // - Allow stack-allocated MockCallbacks to be short-lived, while | |
68 // callbacks go through a long-lived MockCallbackTracker | |
69 // (which in the future can enable better handling of callback- | |
70 // -run-after-mock-callback-already-destroyed). | |
71 class MockCallbackTracker | |
72 : public base::RefCountedThreadSafe<MockCallbackTracker> { | |
73 public: | |
74 MockCallbackTracker(MockCallback* mock_callback) | |
75 : mock_callback_(mock_callback) { | |
76 } | |
77 | |
78 R Run() { | |
79 // Forward to (gMock controlled) MockCallback::Run method. | |
80 return mock_callback_->Run(); | |
81 } | |
82 | |
83 private: | |
84 // Ref-counting helpers. | |
85 friend class base::RefCountedThreadSafe<MockCallbackTracker>; | |
86 ~MockCallbackTracker() { | |
87 } | |
88 | |
89 MockCallback<R()>* mock_callback_; | |
90 }; | |
91 | |
92 scoped_refptr<MockCallbackTracker> mock_callback_tracker_; | |
93 | |
36 DISALLOW_COPY_AND_ASSIGN(MockCallback); | 94 DISALLOW_COPY_AND_ASSIGN(MockCallback); |
37 }; | 95 }; |
38 | 96 |
97 template <typename R, typename A1> | |
98 class MockCallback<R(A1)> { | |
99 public: | |
100 MOCK_CONST_METHOD1_T(Run, R(A1)); | |
101 | |
102 MockCallback() : mock_callback_tracker_(new MockCallbackTracker(this)) { | |
103 } | |
104 | |
105 // Caller of GetCallback has to guarantee that the returned callback | |
106 // will not be run after |this| is destroyed. | |
107 base::Callback<R(A1)> GetCallback() { | |
108 return base::Bind(&MockCallbackTracker::Run, mock_callback_tracker_); | |
109 } | |
110 | |
111 // Returns |true| if callbacks returned by |GetCallback| have not been | |
112 // destroyed yet. | |
113 bool HasRemainingCallbacks() const { | |
114 bool is_tracker_field_the_only_ref = mock_callback_tracker_->HasOneRef(); | |
115 return !is_tracker_field_the_only_ref; | |
116 } | |
117 | |
118 private: | |
119 // MockCallbackTracker has 2 goals: | |
120 // - Enable counting of callbacks for |HasRemainingCallbacks| method. | |
121 // - Allow stack-allocated MockCallbacks to be short-lived, while | |
122 // callbacks go through a long-lived MockCallbackTracker | |
123 // (which in the future can enable better handling of callback- | |
124 // -run-after-mock-callback-already-destroyed). | |
125 class MockCallbackTracker | |
126 : public base::RefCountedThreadSafe<MockCallbackTracker> { | |
127 public: | |
128 MockCallbackTracker(MockCallback* mock_callback) | |
129 : mock_callback_(mock_callback) { | |
130 } | |
131 | |
132 R Run(A1 a1) { | |
133 // Forward to (gMock controlled) MockCallback::Run method. | |
134 return mock_callback_->Run(a1); | |
135 } | |
136 | |
137 private: | |
138 // Ref-counting helpers. | |
139 friend class base::RefCountedThreadSafe<MockCallbackTracker>; | |
140 ~MockCallbackTracker() { | |
141 } | |
142 | |
143 MockCallback<R(A1)>* mock_callback_; | |
144 }; | |
145 | |
146 scoped_refptr<MockCallbackTracker> mock_callback_tracker_; | |
147 | |
148 DISALLOW_COPY_AND_ASSIGN(MockCallback); | |
149 }; | |
150 | |
39 typedef MockCallback<void(void)> MockClosure; | 151 typedef MockCallback<void(void)> MockClosure; |
40 | 152 |
41 } // namespace remoting | 153 } // namespace remoting |
42 | 154 |
43 #endif // REMOTING_HOST_MOCK_CALLBACK_H_ | 155 #endif // REMOTING_HOST_MOCK_CALLBACK_H_ |
OLD | NEW |