Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: mojo/public/cpp/bindings/tests/binding_callback_unittest.cc

Issue 1003773002: CPP bindings: DCHECK when a Callback is destructed without being invoked (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased again Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/public/cpp/bindings/interface_ptr.h"
6 #include "mojo/public/cpp/environment/environment.h"
7 #include "mojo/public/cpp/test_support/test_support.h"
8 #include "mojo/public/cpp/utility/run_loop.h"
9 #include "mojo/public/interfaces/bindings/tests/binding_callback_test_interfaces .mojom.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 ///////////////////////////////////////////////////////////////////////////////
13 //
14 // The tests in this file are designed to test the interaction between a
15 // Callback and its associated Binding. If a Callback is deleted before
16 // being used we DCHECK fail--unless the associated Binding has already
17 // been closed or deleted. This contract must be explained to the Mojo
18 // application developer. For example it is the developer's responsibility to
19 // ensure that the Binding is destroyed before an unused Callback is destroyed.
20 //
21 ///////////////////////////////////////////////////////////////////////////////
22
23 namespace mojo {
24 namespace test {
25 namespace {
26
27 // A Runnable object that saves the last value it sees via the
28 // provided int32_t*. Used on the client side.
29 class ValueSaver {
30 public:
31 explicit ValueSaver(int32_t* last_value_seen)
32 : last_value_seen_(last_value_seen) {}
33 void Run(int32_t x) const { *last_value_seen_ = x; }
34
35 private:
36 int32_t* const last_value_seen_;
37 };
38
39 // An implementation of BindingCallbackTestInterface used on the server side.
40 // All it does is save the values and Callbacks it sees.
41 class BindingCallbackTestInterfaceImpl : public BindingCallbackTestInterface {
42 public:
43 BindingCallbackTestInterfaceImpl()
44 : last_server_value_seen_(0),
45 callback_saved_(new Callback<void(int32_t)>()) {}
46
47 ~BindingCallbackTestInterfaceImpl() override {
48 if (callback_saved_) {
49 delete callback_saved_;
50 }
51 }
52
53 // Run's the callback previously saved from the last invocation
54 // of |EchoInt()|.
55 bool RunCallback() {
56 if (callback_saved_) {
57 callback_saved_->Run(last_server_value_seen_);
58 return true;
59 }
60 return false;
61 }
62
63 // Delete's the previously saved callback.
64 void DeleteCallback() {
65 delete callback_saved_;
66 callback_saved_ = nullptr;
67 }
68
69 // Saves its two input values in member variables and does nothing else.
70 void EchoInt(int32_t x, const Callback<void(int32_t)>& callback) {
71 last_server_value_seen_ = x;
72 *callback_saved_ = callback;
73 }
74
75 void resetLastServerValueSeen() { last_server_value_seen_ = 0; }
76
77 int32_t last_server_value_seen() const { return last_server_value_seen_; }
78
79 private:
80 int32_t last_server_value_seen_;
81 Callback<void(int32_t)>* callback_saved_;
82 };
83
84 class BindingCallbackTest : public testing::Test {
85 public:
86 ~BindingCallbackTest() override {}
87
88 protected:
89 int32_t last_client_callback_value_seen_;
90 ScopedMessagePipeHandle handle_client_;
91 ScopedMessagePipeHandle handle_server_;
92 BindingCallbackTestInterfacePtr interface_ptr_;
93
94 void PumpMessages() { loop_.RunUntilIdle(); }
95 void SetUp() {
96 CreateMessagePipe(nullptr, &handle_client_, &handle_server_);
97 // Create the client InterfacePtr.
98 interface_ptr_ =
99 MakeProxy<BindingCallbackTestInterface>(handle_client_.Pass());
100 }
101
102 private:
103 Environment env_;
104 RunLoop loop_;
105 };
106
107 // Tests that the InterfacePtr and the Binding can communicate with each
108 // other normally.
109 TEST_F(BindingCallbackTest, Basic) {
110 // Create the ServerImpl and the Binding.
111 BindingCallbackTestInterfaceImpl server_impl;
112 Binding<BindingCallbackTestInterface> binding(
113 &server_impl,
114 MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));
115
116 // Initialize the test values.
117 server_impl.resetLastServerValueSeen();
118 last_client_callback_value_seen_ = 0;
119
120 // Invoke the Echo method.
121 interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
122 PumpMessages();
123
124 // Check that server saw the correct value, but the client has not yet.
125 EXPECT_EQ(7, server_impl.last_server_value_seen());
126 EXPECT_EQ(0, last_client_callback_value_seen_);
127
128 // Now run the Callback.
129 server_impl.RunCallback();
130 PumpMessages();
131
132 // Check that the client has now seen the correct value.
133 EXPECT_EQ(7, last_client_callback_value_seen_);
134
135 // Initialize the test values again.
136 server_impl.resetLastServerValueSeen();
137 last_client_callback_value_seen_ = 0;
138
139 // Invoke the Echo method again.
140 interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
141 PumpMessages();
142
143 // Check that server saw the correct value, but the client has not yet.
144 EXPECT_EQ(13, server_impl.last_server_value_seen());
145 EXPECT_EQ(0, last_client_callback_value_seen_);
146
147 // Now run the Callback again.
148 server_impl.RunCallback();
149 PumpMessages();
150
151 // Check that the client has now seen the correct value again.
152 EXPECT_EQ(13, last_client_callback_value_seen_);
153 }
154
155 // Tests that running the Callback after the Binding has been deleted
156 // results in a clean failure.
157 TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) {
158 // Create the ServerImpl.
159 BindingCallbackTestInterfaceImpl server_impl;
160 {
161 // Create the binding in an inner scope so it can be deleted first.
162 Binding<BindingCallbackTestInterface> binding(
163 &server_impl,
164 MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));
165
166 // Initialize the test values.
167 server_impl.resetLastServerValueSeen();
168 last_client_callback_value_seen_ = 0;
169
170 // Invoke the Echo method.
171 interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
172 PumpMessages();
173 }
174 // The binding has now been destroyed and the pipe is closed.
175
176 // Check that server saw the correct value, but the client has not yet.
177 EXPECT_EQ(7, server_impl.last_server_value_seen());
178 EXPECT_EQ(0, last_client_callback_value_seen_);
179
180 // Now try to run the Callback. This should do nothing since the pipe
181 // is closed.
182 EXPECT_TRUE(server_impl.RunCallback());
183 PumpMessages();
184
185 // Check that the client has still not seen the correct value.
186 EXPECT_EQ(0, last_client_callback_value_seen_);
187
188 // Attempt to invoke the method again and confirm that an error was
189 // encountered.
190 interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
191 PumpMessages();
192 EXPECT_TRUE(interface_ptr_.encountered_error());
193 }
194
195 // Tests that deleting a Callback without running it after the corresponding
196 // binding has already been deleted does not result in a crash.
197 TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
198 // Create the ServerImpl.
199 BindingCallbackTestInterfaceImpl server_impl;
200 {
201 // Create the binding in an inner scope so it can be deleted first.
202 Binding<BindingCallbackTestInterface> binding(
203 &server_impl,
204 MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));
205
206 // Initialize the test values.
207 server_impl.resetLastServerValueSeen();
208 last_client_callback_value_seen_ = 0;
209
210 // Invoke the Echo method.
211 interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
212 PumpMessages();
213 }
214 // The binding has now been destroyed and the pipe is closed.
215
216 // Check that server saw the correct value, but the client has not yet.
217 EXPECT_EQ(7, server_impl.last_server_value_seen());
218 EXPECT_EQ(0, last_client_callback_value_seen_);
219
220 // Delete the callback without running it. This should not
221 // cause a problem because the insfrastructure can detect that the
222 // binding has already been destroyed and the pipe is closed.
223 server_impl.DeleteCallback();
224 }
225
226 // Tests that closing a Binding allows us to delete a callback
227 // without running it without encountering a crash.
228 TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
229 // Create the ServerImpl and the Binding.
230 BindingCallbackTestInterfaceImpl server_impl;
231 Binding<BindingCallbackTestInterface> binding(
232 &server_impl,
233 MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));
234
235 // Initialize the test values.
236 server_impl.resetLastServerValueSeen();
237 last_client_callback_value_seen_ = 0;
238
239 // Invoke the Echo method.
240 interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
241 PumpMessages();
242
243 // Check that server saw the correct value, but the client has not yet.
244 EXPECT_EQ(7, server_impl.last_server_value_seen());
245 EXPECT_EQ(0, last_client_callback_value_seen_);
246
247 // Now close the Binding.
248 binding.Close();
249
250 // Delete the callback without running it. This should not
251 // cause a crash because the insfrastructure can detect that the
252 // binding has already been closed.
253 server_impl.DeleteCallback();
254
255 // Check that the client has still not seen the correct value.
256 EXPECT_EQ(0, last_client_callback_value_seen_);
257 }
258
259 // Tests that deleting a Callback without using it before the
260 // Binding has been destroyed or closed results in a DCHECK.
261 TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) {
262 // Create the ServerImpl and the Binding.
263 BindingCallbackTestInterfaceImpl server_impl;
264 Binding<BindingCallbackTestInterface> binding(
265 &server_impl,
266 MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));
267
268 // Initialize the test values.
269 server_impl.resetLastServerValueSeen();
270 last_client_callback_value_seen_ = 0;
271
272 // Invoke the Echo method.
273 interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
274 PumpMessages();
275
276 // Check that server saw the correct value, but the client has not yet.
277 EXPECT_EQ(7, server_impl.last_server_value_seen());
278 EXPECT_EQ(0, last_client_callback_value_seen_);
279
280 // Delete the callback without running it. This should cause a crash
281 // due to a DCHECK.
282 EXPECT_DEATH(server_impl.DeleteCallback(),
283 "Check failed: !callback_was_dropped.");
284 }
285
286 } // namespace
287 } // namespace test
288 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/BUILD.gn ('k') | mojo/public/cpp/bindings/tests/router_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698