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

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

Powered by Google App Engine
This is Rietveld 408576698