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 "build/build_config.h"
13 #include "mojo/public/cpp/bindings/binding.h"
14 #include "mojo/public/cpp/bindings/interface_ptr.h"
15 #include "mojo/public/cpp/bindings/string.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, GetProxy(&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, GetProxy(&interface_ptr_));
203 interface_ptr_.set_connection_error_handler(run_loop.QuitClosure());
204
205 // Initialize the test values.
206 server_impl.resetLastServerValueSeen();
207 last_client_callback_value_seen_ = 0;
208
209 // Invoke the Echo method.
210 base::RunLoop run_loop2;
211 server_impl.set_closure(run_loop2.QuitClosure());
212 interface_ptr_->EchoInt(
213 7,
214 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
215 run_loop2.Run();
216 }
217 // The binding has now been destroyed and the pipe is closed.
218
219 // Check that server saw the correct value, but the client has not yet.
220 EXPECT_EQ(7, server_impl.last_server_value_seen());
221 EXPECT_EQ(0, last_client_callback_value_seen_);
222
223 // Now try to run the Callback. This should do nothing since the pipe
224 // is closed.
225 EXPECT_TRUE(server_impl.RunCallback());
226 PumpMessages();
227
228 // Check that the client has still not seen the correct value.
229 EXPECT_EQ(0, last_client_callback_value_seen_);
230
231 // Attempt to invoke the method again and confirm that an error was
232 // encountered.
233 interface_ptr_->EchoInt(
234 13,
235 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
236 run_loop.Run();
237 EXPECT_TRUE(interface_ptr_.encountered_error());
238 }
239
240 // Tests that deleting a Callback without running it after the corresponding
241 // binding has already been deleted does not result in a crash.
TEST_F(BindingCallbackTest,DeleteBindingThenDeleteCallback)242 TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
243 // Create the ServerImpl.
244 InterfaceImpl server_impl;
245 {
246 // Create the binding in an inner scope so it can be deleted first.
247 Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
248
249 // Initialize the test values.
250 server_impl.resetLastServerValueSeen();
251 last_client_callback_value_seen_ = 0;
252
253 // Invoke the Echo method.
254 base::RunLoop run_loop;
255 server_impl.set_closure(run_loop.QuitClosure());
256 interface_ptr_->EchoInt(
257 7,
258 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
259 run_loop.Run();
260 }
261 // The binding has now been destroyed and the pipe is closed.
262
263 // Check that server saw the correct value, but the client has not yet.
264 EXPECT_EQ(7, server_impl.last_server_value_seen());
265 EXPECT_EQ(0, last_client_callback_value_seen_);
266
267 // Delete the callback without running it. This should not
268 // cause a problem because the insfrastructure can detect that the
269 // binding has already been destroyed and the pipe is closed.
270 server_impl.DeleteCallback();
271 }
272
273 // Tests that closing a Binding allows us to delete a callback
274 // without running it without encountering a crash.
TEST_F(BindingCallbackTest,CloseBindingBeforeDeletingCallback)275 TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
276 // Create the ServerImpl and the Binding.
277 InterfaceImpl server_impl;
278 Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
279
280 // Initialize the test values.
281 server_impl.resetLastServerValueSeen();
282 last_client_callback_value_seen_ = 0;
283
284 // Invoke the Echo method.
285 base::RunLoop run_loop;
286 server_impl.set_closure(run_loop.QuitClosure());
287 interface_ptr_->EchoInt(
288 7,
289 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
290 run_loop.Run();
291
292 // Check that server saw the correct value, but the client has not yet.
293 EXPECT_EQ(7, server_impl.last_server_value_seen());
294 EXPECT_EQ(0, last_client_callback_value_seen_);
295
296 // Now close the Binding.
297 binding.Close();
298
299 // Delete the callback without running it. This should not
300 // cause a crash because the insfrastructure can detect that the
301 // binding has already been closed.
302 server_impl.DeleteCallback();
303
304 // Check that the client has still not seen the correct value.
305 EXPECT_EQ(0, last_client_callback_value_seen_);
306 }
307
308 // Tests that deleting a Callback without using it before the
309 // Binding has been destroyed or closed results in a DCHECK.
TEST_F(BindingCallbackTest,DeleteCallbackBeforeBindingDeathTest)310 TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) {
311 // Create the ServerImpl and the Binding.
312 InterfaceImpl server_impl;
313 Binding<sample::Provider> binding(&server_impl, GetProxy(&interface_ptr_));
314
315 // Initialize the test values.
316 server_impl.resetLastServerValueSeen();
317 last_client_callback_value_seen_ = 0;
318
319 // Invoke the Echo method.
320 base::RunLoop run_loop;
321 server_impl.set_closure(run_loop.QuitClosure());
322 interface_ptr_->EchoInt(
323 7,
324 BindValueSaver(&last_client_callback_value_seen_, base::Closure()));
325 run_loop.Run();
326
327 // Check that server saw the correct value, but the client has not yet.
328 EXPECT_EQ(7, server_impl.last_server_value_seen());
329 EXPECT_EQ(0, last_client_callback_value_seen_);
330
331 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && !defined(OS_ANDROID)
332 // Delete the callback without running it. This should cause a crash in debug
333 // builds due to a DCHECK.
334 std::string regex("Check failed: !is_valid");
335 #if defined(OS_WIN)
336 // TODO(msw): Fix MOJO_DCHECK logs and EXPECT_DEATH* on Win: crbug.com/535014
337 regex.clear();
338 #endif // OS_WIN
339 EXPECT_DEATH_IF_SUPPORTED(server_impl.DeleteCallback(), regex.c_str());
340 #endif // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) &&
341 // !defined(OS_ANDROID)
342 }
343
344 } // namespace
345 } // namespace test
346 } // namespace mojo
347