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 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 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: 52 InterfaceImpl() 53 : last_server_value_seen_(0), 54 callback_saved_(new EchoIntCallback) {} 55 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()|. 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. 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. 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 90 void EchoString(const std::string& a, 91 const EchoStringCallback& callback) override { 92 CHECK(false) << "Not implemented."; 93 } 94 95 void EchoStrings(const std::string& a, 96 const std::string& b, 97 const EchoStringsCallback& callback) override { 98 CHECK(false) << "Not implemented."; 99 } 100 101 void EchoMessagePipeHandle( 102 ScopedMessagePipeHandle a, 103 const EchoMessagePipeHandleCallback& callback) override { 104 CHECK(false) << "Not implemented."; 105 } 106 107 void EchoEnum(sample::Enum a, const EchoEnumCallback& callback) override { 108 CHECK(false) << "Not implemented."; 109 } 110 111 void resetLastServerValueSeen() { last_server_value_seen_ = 0; } 112 113 int32_t last_server_value_seen() const { return last_server_value_seen_; } 114 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: 125 BindingCallbackTest() {} 126 ~BindingCallbackTest() override {} 127 128 protected: 129 int32_t last_client_callback_value_seen_; 130 sample::ProviderPtr interface_ptr_; 131 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. 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. 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. 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. 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. 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