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