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