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 <stdint.h>
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/test/gtest_util.h"
13 #include "build/build_config.h"
14 #include "mojo/public/cpp/bindings/binding.h"
15 #include "mojo/public/cpp/bindings/interface_ptr.h"
16 #include "mojo/public/cpp/system/message_pipe.h"
17 #include "mojo/public/cpp/test_support/test_support.h"
18 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 ///////////////////////////////////////////////////////////////////////////////
22 //
23 // The tests in this file are designed to test the interaction between a
24 // Callback and its associated Binding. If a Callback is deleted before
25 // being used we DCHECK fail--unless the associated Binding has already
26 // been closed or deleted. This contract must be explained to the Mojo
27 // application developer. For example it is the developer's responsibility to
28 // ensure that the Binding is destroyed before an unused Callback is destroyed.
29 //
30 ///////////////////////////////////////////////////////////////////////////////
31
32 namespace mojo {
33 namespace test {
34 namespace {
35
SaveValue(int32_t * storage,const base::Closure & closure,int32_t value)36 void SaveValue(int32_t* storage, const base::Closure& closure, int32_t value) {
37 *storage = value;
38 if (!closure.is_null())
39 closure.Run();
40 }
41
BindValueSaver(int32_t * last_value_seen,const base::Closure & closure)42 base::Callback<void(int32_t)> BindValueSaver(int32_t* last_value_seen,
43 const base::Closure& closure) {
44 return base::Bind(&SaveValue, last_value_seen, closure);
45 }
46
47 // An implementation of sample::Provider used on the server side.
48 // It only implements one of the methods: EchoInt().
49 // All it does is save the values and Callbacks it sees.
50 class InterfaceImpl : public sample::Provider {
51 public:
InterfaceImpl()52 InterfaceImpl()
53 : last_server_value_seen_(0),
54 callback_saved_(new EchoIntCallback) {}
55
~InterfaceImpl()56 ~InterfaceImpl() override {
57 if (callback_saved_) {
58 delete callback_saved_;
59 }
60 }
61
62 // Run's the callback previously saved from the last invocation
63 // of |EchoInt()|.
RunCallback()64 bool RunCallback() {
65 if (callback_saved_) {
66 callback_saved_->Run(last_server_value_seen_);
67 return true;
68 }
69 return false;
70 }
71
72 // Delete's the previously saved callback.
DeleteCallback()73 void DeleteCallback() {
74 delete callback_saved_;
75 callback_saved_ = nullptr;
76 }
77
78 // sample::Provider implementation
79
80 // Saves its two input values in member variables and does nothing else.
EchoInt(int32_t x,const EchoIntCallback & callback)81 void EchoInt(int32_t x, const EchoIntCallback& callback) override {
82 last_server_value_seen_ = x;
83 *callback_saved_ = callback;
84 if (!closure_.is_null()) {
85 closure_.Run();
86 closure_.Reset();
87 }
88 }
89
EchoString(const std::string & a,const EchoStringCallback & callback)90 void EchoString(const std::string& a,
91 const EchoStringCallback& callback) override {
92 CHECK(false) << "Not implemented.";
93 }
94
EchoStrings(const std::string & a,const std::string & b,const EchoStringsCallback & callback)95 void EchoStrings(const std::string& a,
96 const std::string& b,
97 const EchoStringsCallback& callback) override {
98 CHECK(false) << "Not implemented.";
99 }
100
EchoMessagePipeHandle(ScopedMessagePipeHandle a,const EchoMessagePipeHandleCallback & callback)101 void EchoMessagePipeHandle(
102 ScopedMessagePipeHandle a,
103 const EchoMessagePipeHandleCallback& callback) override {
104 CHECK(false) << "Not implemented.";
105 }
106
EchoEnum(sample::Enum a,const EchoEnumCallback & callback)107 void EchoEnum(sample::Enum a, const EchoEnumCallback& callback) override {
108 CHECK(false) << "Not implemented.";
109 }
110
resetLastServerValueSeen()111 void resetLastServerValueSeen() { last_server_value_seen_ = 0; }
112
last_server_value_seen() const113 int32_t last_server_value_seen() const { return last_server_value_seen_; }
114
set_closure(const base::Closure & closure)115 void set_closure(const base::Closure& closure) { closure_ = closure; }
116
117 private:
118 int32_t last_server_value_seen_;
119 EchoIntCallback* callback_saved_;
120 base::Closure closure_;
121 };
122
123 class BindingCallbackTest : public testing::Test {
124 public:
BindingCallbackTest()125 BindingCallbackTest() {}
~BindingCallbackTest()126 ~BindingCallbackTest() override {}
127
128 protected:
129 int32_t last_client_callback_value_seen_;
130 sample::ProviderPtr interface_ptr_;
131
PumpMessages()132 void PumpMessages() { base::RunLoop().RunUntilIdle(); }
133
134 private:
135 base::MessageLoop loop_;
136 };
137
138 // Tests that the InterfacePtr and the Binding can communicate with each
139 // other normally.
TEST_F(BindingCallbackTest,Basic)140 TEST_F(BindingCallbackTest, Basic) {
141 // Create the ServerImpl and the Binding.
142 InterfaceImpl server_impl;
143 Binding<sample::Provider> binding(&server_impl, MakeRequest(&interface_ptr_));
144
145 // Initialize the test values.
146 server_impl.resetLastServerValueSeen();
147 last_client_callback_value_seen_ = 0;
148
149 // Invoke the Echo method.
150 base::RunLoop run_loop, run_loop2;
151 server_impl.set_closure(run_loop.QuitClosure());
152 interface_ptr_->EchoInt(
153 7,
154 BindValueSaver(&last_client_callback_value_seen_,
155 run_loop2.QuitClosure()));
156 run_loop.Run();
157
158 // Check that server saw the correct value, but the client has not yet.
159 EXPECT_EQ(7, server_impl.last_server_value_seen());
160 EXPECT_EQ(0, last_client_callback_value_seen_);
161
162 // Now run the Callback.
163 server_impl.RunCallback();
164 run_loop2.Run();
165
166 // Check that the client has now seen the correct value.
167 EXPECT_EQ(7, last_client_callback_value_seen_);
168
169 // Initialize the test values again.
170 server_impl.resetLastServerValueSeen();
171 last_client_callback_value_seen_ = 0;
172
173 // Invoke the Echo method again.
174 base::RunLoop run_loop3, run_loop4;
175 server_impl.set_closure(run_loop3.QuitClosure());
176 interface_ptr_->EchoInt(
177 13,
178 BindValueSaver(&last_client_callback_value_seen_,
179 run_loop4.QuitClosure()));
180 run_loop3.Run();
181
182 // Check that server saw the correct value, but the client has not yet.
183 EXPECT_EQ(13, server_impl.last_server_value_seen());
184 EXPECT_EQ(0, last_client_callback_value_seen_);
185
186 // Now run the Callback again.
187 server_impl.RunCallback();
188 run_loop4.Run();
189
190 // Check that the client has now seen the correct value again.
191 EXPECT_EQ(13, last_client_callback_value_seen_);
192 }
193
194 // Tests that running the Callback after the Binding has been deleted
195 // results in a clean failure.
TEST_F(BindingCallbackTest,DeleteBindingThenRunCallback)196 TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) {
197 // Create the ServerImpl.
198 InterfaceImpl server_impl;
199 base::RunLoop run_loop;
200 {
201 // Create the binding in an inner scope so it can be deleted first.
202 Binding<sample::Provider> binding(&server_impl,
203 MakeRequest(&interface_ptr_));
204 interface_ptr_.set_connection_error_handler(run_loop.QuitClosure());
205
206 // Initialize the test values.
207 server_impl.resetLastServerValueSeen();
208 last_client_callback_value_seen_ = 0;
209
210 // Invoke the Echo method.
211 base::RunLoop run_loop2;
212 server_impl.set_closure(run_loop2.QuitClosure());
213 interface_ptr_->EchoInt(
214 7,
215 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
216 run_loop2.Run();
217 }
218 // The binding has now been destroyed and the pipe is closed.
219
220 // Check that server saw the correct value, but the client has not yet.
221 EXPECT_EQ(7, server_impl.last_server_value_seen());
222 EXPECT_EQ(0, last_client_callback_value_seen_);
223
224 // Now try to run the Callback. This should do nothing since the pipe
225 // is closed.
226 EXPECT_TRUE(server_impl.RunCallback());
227 PumpMessages();
228
229 // Check that the client has still not seen the correct value.
230 EXPECT_EQ(0, last_client_callback_value_seen_);
231
232 // Attempt to invoke the method again and confirm that an error was
233 // encountered.
234 interface_ptr_->EchoInt(
235 13,
236 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
237 run_loop.Run();
238 EXPECT_TRUE(interface_ptr_.encountered_error());
239 }
240
241 // Tests that deleting a Callback without running it after the corresponding
242 // binding has already been deleted does not result in a crash.
TEST_F(BindingCallbackTest,DeleteBindingThenDeleteCallback)243 TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
244 // Create the ServerImpl.
245 InterfaceImpl server_impl;
246 {
247 // Create the binding in an inner scope so it can be deleted first.
248 Binding<sample::Provider> binding(&server_impl,
249 MakeRequest(&interface_ptr_));
250
251 // Initialize the test values.
252 server_impl.resetLastServerValueSeen();
253 last_client_callback_value_seen_ = 0;
254
255 // Invoke the Echo method.
256 base::RunLoop run_loop;
257 server_impl.set_closure(run_loop.QuitClosure());
258 interface_ptr_->EchoInt(
259 7,
260 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
261 run_loop.Run();
262 }
263 // The binding has now been destroyed and the pipe is closed.
264
265 // Check that server saw the correct value, but the client has not yet.
266 EXPECT_EQ(7, server_impl.last_server_value_seen());
267 EXPECT_EQ(0, last_client_callback_value_seen_);
268
269 // Delete the callback without running it. This should not
270 // cause a problem because the insfrastructure can detect that the
271 // binding has already been destroyed and the pipe is closed.
272 server_impl.DeleteCallback();
273 }
274
275 // Tests that closing a Binding allows us to delete a callback
276 // without running it without encountering a crash.
TEST_F(BindingCallbackTest,CloseBindingBeforeDeletingCallback)277 TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
278 // Create the ServerImpl and the Binding.
279 InterfaceImpl server_impl;
280 Binding<sample::Provider> binding(&server_impl, MakeRequest(&interface_ptr_));
281
282 // Initialize the test values.
283 server_impl.resetLastServerValueSeen();
284 last_client_callback_value_seen_ = 0;
285
286 // Invoke the Echo method.
287 base::RunLoop run_loop;
288 server_impl.set_closure(run_loop.QuitClosure());
289 interface_ptr_->EchoInt(
290 7,
291 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
292 run_loop.Run();
293
294 // Check that server saw the correct value, but the client has not yet.
295 EXPECT_EQ(7, server_impl.last_server_value_seen());
296 EXPECT_EQ(0, last_client_callback_value_seen_);
297
298 // Now close the Binding.
299 binding.Close();
300
301 // Delete the callback without running it. This should not
302 // cause a crash because the insfrastructure can detect that the
303 // binding has already been closed.
304 server_impl.DeleteCallback();
305
306 // Check that the client has still not seen the correct value.
307 EXPECT_EQ(0, last_client_callback_value_seen_);
308 }
309
310 // Tests that deleting a Callback without using it before the
311 // Binding has been destroyed or closed results in a DCHECK.
TEST_F(BindingCallbackTest,DeleteCallbackBeforeBindingDeathTest)312 TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) {
313 // Create the ServerImpl and the Binding.
314 InterfaceImpl server_impl;
315 Binding<sample::Provider> binding(&server_impl, MakeRequest(&interface_ptr_));
316
317 // Initialize the test values.
318 server_impl.resetLastServerValueSeen();
319 last_client_callback_value_seen_ = 0;
320
321 // Invoke the Echo method.
322 base::RunLoop run_loop;
323 server_impl.set_closure(run_loop.QuitClosure());
324 interface_ptr_->EchoInt(
325 7,
326 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
327 run_loop.Run();
328
329 // Check that server saw the correct value, but the client has not yet.
330 EXPECT_EQ(7, server_impl.last_server_value_seen());
331 EXPECT_EQ(0, last_client_callback_value_seen_);
332
333 EXPECT_DCHECK_DEATH(server_impl.DeleteCallback());
334 }
335
336 } // namespace
337 } // namespace test
338 } // namespace mojo
339