• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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