| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Note: This file tests both binding.h (mojo::Binding) and strong_binding.h | 5 // Note: This file tests both binding.h (mojo::Binding) and strong_binding.h |
| 6 // (mojo::StrongBinding). | 6 // (mojo::StrongBinding). |
| 7 | 7 |
| 8 #include "mojo/public/cpp/bindings/binding.h" | 8 #include "mojo/public/cpp/bindings/binding.h" |
| 9 | 9 |
| 10 #include <stdint.h> | 10 #include <stdint.h> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/run_loop.h" |
| 14 #include "mojo/message_pump/message_pump_mojo.h" | 15 #include "mojo/message_pump/message_pump_mojo.h" |
| 15 #include "mojo/public/cpp/bindings/strong_binding.h" | 16 #include "mojo/public/cpp/bindings/strong_binding.h" |
| 16 #include "mojo/public/cpp/system/macros.h" | 17 #include "mojo/public/cpp/system/macros.h" |
| 17 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" | 18 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" |
| 18 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" | 19 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 21 |
| 21 namespace mojo { | 22 namespace mojo { |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 }; | 60 }; |
| 60 | 61 |
| 61 // BindingTest ----------------------------------------------------------------- | 62 // BindingTest ----------------------------------------------------------------- |
| 62 | 63 |
| 63 using BindingTest = BindingTestBase; | 64 using BindingTest = BindingTestBase; |
| 64 | 65 |
| 65 TEST_F(BindingTest, Close) { | 66 TEST_F(BindingTest, Close) { |
| 66 bool called = false; | 67 bool called = false; |
| 67 sample::ServicePtr ptr; | 68 sample::ServicePtr ptr; |
| 68 auto request = GetProxy(&ptr); | 69 auto request = GetProxy(&ptr); |
| 69 ptr.set_connection_error_handler([&called]() { called = true; }); | 70 base::RunLoop run_loop; |
| 71 ptr.set_connection_error_handler([&called, &run_loop]() { |
| 72 called = true; |
| 73 run_loop.Quit(); |
| 74 }); |
| 70 ServiceImpl impl; | 75 ServiceImpl impl; |
| 71 Binding<sample::Service> binding(&impl, std::move(request)); | 76 Binding<sample::Service> binding(&impl, std::move(request)); |
| 72 | 77 |
| 73 binding.Close(); | 78 binding.Close(); |
| 74 EXPECT_FALSE(called); | 79 EXPECT_FALSE(called); |
| 75 loop().RunUntilIdle(); | 80 run_loop.Run(); |
| 76 EXPECT_TRUE(called); | 81 EXPECT_TRUE(called); |
| 77 } | 82 } |
| 78 | 83 |
| 79 // Tests that destroying a mojo::Binding closes the bound message pipe handle. | 84 // Tests that destroying a mojo::Binding closes the bound message pipe handle. |
| 80 TEST_F(BindingTest, DestroyClosesMessagePipe) { | 85 TEST_F(BindingTest, DestroyClosesMessagePipe) { |
| 81 bool encountered_error = false; | 86 bool encountered_error = false; |
| 82 ServiceImpl impl; | 87 ServiceImpl impl; |
| 83 sample::ServicePtr ptr; | 88 sample::ServicePtr ptr; |
| 84 auto request = GetProxy(&ptr); | 89 auto request = GetProxy(&ptr); |
| 90 base::RunLoop run_loop; |
| 85 ptr.set_connection_error_handler( | 91 ptr.set_connection_error_handler( |
| 86 [&encountered_error]() { encountered_error = true; }); | 92 [&encountered_error, &run_loop]() { |
| 93 encountered_error = true; |
| 94 run_loop.Quit(); |
| 95 }); |
| 87 bool called = false; | 96 bool called = false; |
| 88 auto called_cb = [&called](int32_t result) { called = true; }; | 97 base::RunLoop run_loop2; |
| 98 auto called_cb = [&called, &run_loop2](int32_t result) { |
| 99 called = true; |
| 100 run_loop2.Quit(); |
| 101 }; |
| 89 { | 102 { |
| 90 Binding<sample::Service> binding(&impl, std::move(request)); | 103 Binding<sample::Service> binding(&impl, std::move(request)); |
| 91 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 104 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 92 called_cb); | 105 called_cb); |
| 93 loop().RunUntilIdle(); | 106 run_loop2.Run(); |
| 94 EXPECT_TRUE(called); | 107 EXPECT_TRUE(called); |
| 95 EXPECT_FALSE(encountered_error); | 108 EXPECT_FALSE(encountered_error); |
| 96 } | 109 } |
| 97 // Now that the Binding is out of scope we should detect an error on the other | 110 // Now that the Binding is out of scope we should detect an error on the other |
| 98 // end of the pipe. | 111 // end of the pipe. |
| 99 loop().RunUntilIdle(); | 112 run_loop.Run(); |
| 100 EXPECT_TRUE(encountered_error); | 113 EXPECT_TRUE(encountered_error); |
| 101 | 114 |
| 102 // And calls should fail. | 115 // And calls should fail. |
| 103 called = false; | 116 called = false; |
| 104 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 117 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 105 called_cb); | 118 called_cb); |
| 106 loop().RunUntilIdle(); | 119 loop().RunUntilIdle(); |
| 107 EXPECT_FALSE(called); | 120 EXPECT_FALSE(called); |
| 108 } | 121 } |
| 109 | 122 |
| 110 // Tests that the binding's connection error handler gets called when the other | 123 // Tests that the binding's connection error handler gets called when the other |
| 111 // end is closed. | 124 // end is closed. |
| 112 TEST_F(BindingTest, ConnectionError) { | 125 TEST_F(BindingTest, ConnectionError) { |
| 113 bool called = false; | 126 bool called = false; |
| 114 { | 127 { |
| 115 ServiceImpl impl; | 128 ServiceImpl impl; |
| 116 sample::ServicePtr ptr; | 129 sample::ServicePtr ptr; |
| 117 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); | 130 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); |
| 118 binding.set_connection_error_handler([&called]() { called = true; }); | 131 base::RunLoop run_loop; |
| 132 binding.set_connection_error_handler([&called, &run_loop]() { |
| 133 called = true; |
| 134 run_loop.Quit(); |
| 135 }); |
| 119 ptr.reset(); | 136 ptr.reset(); |
| 120 EXPECT_FALSE(called); | 137 EXPECT_FALSE(called); |
| 121 loop().RunUntilIdle(); | 138 run_loop.Run(); |
| 122 EXPECT_TRUE(called); | 139 EXPECT_TRUE(called); |
| 123 // We want to make sure that it isn't called again during destruction. | 140 // We want to make sure that it isn't called again during destruction. |
| 124 called = false; | 141 called = false; |
| 125 } | 142 } |
| 126 EXPECT_FALSE(called); | 143 EXPECT_FALSE(called); |
| 127 } | 144 } |
| 128 | 145 |
| 129 // Tests that calling Close doesn't result in the connection error handler being | 146 // Tests that calling Close doesn't result in the connection error handler being |
| 130 // called. | 147 // called. |
| 131 TEST_F(BindingTest, CloseDoesntCallConnectionErrorHandler) { | 148 TEST_F(BindingTest, CloseDoesntCallConnectionErrorHandler) { |
| 132 ServiceImpl impl; | 149 ServiceImpl impl; |
| 133 sample::ServicePtr ptr; | 150 sample::ServicePtr ptr; |
| 134 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); | 151 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); |
| 135 bool called = false; | 152 bool called = false; |
| 136 binding.set_connection_error_handler([&called]() { called = true; }); | 153 binding.set_connection_error_handler([&called]() { called = true; }); |
| 137 binding.Close(); | 154 binding.Close(); |
| 138 loop().RunUntilIdle(); | 155 loop().RunUntilIdle(); |
| 139 EXPECT_FALSE(called); | 156 EXPECT_FALSE(called); |
| 140 | 157 |
| 141 // We can also close the other end, and the error handler still won't be | 158 // We can also close the other end, and the error handler still won't be |
| 142 // called. | 159 // called. |
| 143 ptr.reset(); | 160 ptr.reset(); |
| 144 loop().RunUntilIdle(); | 161 loop().RunUntilIdle(); |
| 145 EXPECT_FALSE(called); | 162 EXPECT_FALSE(called); |
| 146 } | 163 } |
| 147 | 164 |
| 148 class ServiceImplWithBinding : public ServiceImpl { | 165 class ServiceImplWithBinding : public ServiceImpl { |
| 149 public: | 166 public: |
| 150 ServiceImplWithBinding(bool* was_deleted, | 167 ServiceImplWithBinding(bool* was_deleted, |
| 168 const base::Closure& closure, |
| 151 InterfaceRequest<sample::Service> request) | 169 InterfaceRequest<sample::Service> request) |
| 152 : ServiceImpl(was_deleted), binding_(this, std::move(request)) { | 170 : ServiceImpl(was_deleted), |
| 171 binding_(this, std::move(request)), |
| 172 closure_(closure) { |
| 153 binding_.set_connection_error_handler([this]() { delete this; }); | 173 binding_.set_connection_error_handler([this]() { delete this; }); |
| 154 } | 174 } |
| 155 | 175 |
| 156 private: | 176 private: |
| 177 ~ServiceImplWithBinding() override{ |
| 178 closure_.Run(); |
| 179 } |
| 180 |
| 157 Binding<sample::Service> binding_; | 181 Binding<sample::Service> binding_; |
| 182 base::Closure closure_; |
| 158 | 183 |
| 159 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); | 184 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); |
| 160 }; | 185 }; |
| 161 | 186 |
| 162 // Tests that the binding may be deleted in the connection error handler. | 187 // Tests that the binding may be deleted in the connection error handler. |
| 163 TEST_F(BindingTest, SelfDeleteOnConnectionError) { | 188 TEST_F(BindingTest, SelfDeleteOnConnectionError) { |
| 164 bool was_deleted = false; | 189 bool was_deleted = false; |
| 165 sample::ServicePtr ptr; | 190 sample::ServicePtr ptr; |
| 166 // This should delete itself on connection error. | 191 // This should delete itself on connection error. |
| 167 new ServiceImplWithBinding(&was_deleted, GetProxy(&ptr)); | 192 base::RunLoop run_loop; |
| 193 new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(), |
| 194 GetProxy(&ptr)); |
| 168 ptr.reset(); | 195 ptr.reset(); |
| 169 EXPECT_FALSE(was_deleted); | 196 EXPECT_FALSE(was_deleted); |
| 170 loop().RunUntilIdle(); | 197 run_loop.Run(); |
| 171 EXPECT_TRUE(was_deleted); | 198 EXPECT_TRUE(was_deleted); |
| 172 } | 199 } |
| 173 | 200 |
| 174 // Tests that explicitly calling Unbind followed by rebinding works. | 201 // Tests that explicitly calling Unbind followed by rebinding works. |
| 175 TEST_F(BindingTest, Unbind) { | 202 TEST_F(BindingTest, Unbind) { |
| 176 ServiceImpl impl; | 203 ServiceImpl impl; |
| 177 sample::ServicePtr ptr; | 204 sample::ServicePtr ptr; |
| 178 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); | 205 Binding<sample::Service> binding(&impl, GetProxy(&ptr)); |
| 179 | 206 |
| 180 bool called = false; | 207 bool called = false; |
| 181 auto called_cb = [&called](int32_t result) { called = true; }; | 208 base::RunLoop run_loop; |
| 209 auto called_cb = [&called, &run_loop](int32_t result) { |
| 210 called = true; |
| 211 run_loop.Quit(); |
| 212 }; |
| 182 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 213 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 183 called_cb); | 214 called_cb); |
| 184 loop().RunUntilIdle(); | 215 run_loop.Run(); |
| 185 EXPECT_TRUE(called); | 216 EXPECT_TRUE(called); |
| 186 | 217 |
| 187 called = false; | 218 called = false; |
| 188 auto request = binding.Unbind(); | 219 auto request = binding.Unbind(); |
| 189 EXPECT_FALSE(binding.is_bound()); | 220 EXPECT_FALSE(binding.is_bound()); |
| 190 // All calls should fail when not bound... | 221 // All calls should fail when not bound... |
| 191 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 222 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 192 called_cb); | 223 called_cb); |
| 193 loop().RunUntilIdle(); | 224 loop().RunUntilIdle(); |
| 194 EXPECT_FALSE(called); | 225 EXPECT_FALSE(called); |
| 195 | 226 |
| 196 called = false; | 227 called = false; |
| 197 binding.Bind(std::move(request)); | 228 binding.Bind(std::move(request)); |
| 198 EXPECT_TRUE(binding.is_bound()); | 229 EXPECT_TRUE(binding.is_bound()); |
| 199 // ...and should succeed again when the rebound. | 230 // ...and should succeed again when the rebound. |
| 231 base::RunLoop run_loop2; |
| 232 auto called_cb2 = [&called, &run_loop2](int32_t result) { |
| 233 called = true; |
| 234 run_loop2.Quit(); |
| 235 }; |
| 200 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 236 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 201 called_cb); | 237 called_cb2); |
| 202 loop().RunUntilIdle(); | 238 run_loop2.Run(); |
| 203 EXPECT_TRUE(called); | 239 EXPECT_TRUE(called); |
| 204 } | 240 } |
| 205 | 241 |
| 206 class IntegerAccessorImpl : public sample::IntegerAccessor { | 242 class IntegerAccessorImpl : public sample::IntegerAccessor { |
| 207 public: | 243 public: |
| 208 IntegerAccessorImpl() {} | 244 IntegerAccessorImpl() {} |
| 209 ~IntegerAccessorImpl() override {} | 245 ~IntegerAccessorImpl() override {} |
| 210 | 246 |
| 211 private: | 247 private: |
| 212 // sample::IntegerAccessor implementation. | 248 // sample::IntegerAccessor implementation. |
| 213 void GetInteger(const GetIntegerCallback& callback) override { | 249 void GetInteger(const GetIntegerCallback& callback) override { |
| 214 callback.Run(1, sample::ENUM_VALUE); | 250 callback.Run(1, sample::ENUM_VALUE); |
| 215 } | 251 } |
| 216 void SetInteger(int64_t data, sample::Enum type) override {} | 252 void SetInteger(int64_t data, sample::Enum type) override {} |
| 217 | 253 |
| 218 MOJO_DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl); | 254 MOJO_DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl); |
| 219 }; | 255 }; |
| 220 | 256 |
| 221 TEST_F(BindingTest, SetInterfacePtrVersion) { | 257 TEST_F(BindingTest, SetInterfacePtrVersion) { |
| 222 IntegerAccessorImpl impl; | 258 IntegerAccessorImpl impl; |
| 223 sample::IntegerAccessorPtr ptr; | 259 sample::IntegerAccessorPtr ptr; |
| 224 Binding<sample::IntegerAccessor> binding(&impl, &ptr); | 260 Binding<sample::IntegerAccessor> binding(&impl, &ptr); |
| 225 EXPECT_EQ(3u, ptr.version()); | 261 EXPECT_EQ(3u, ptr.version()); |
| 226 } | 262 } |
| 227 | 263 |
| 228 TEST_F(BindingTest, PauseResume) { | 264 TEST_F(BindingTest, PauseResume) { |
| 229 bool called = false; | 265 bool called = false; |
| 230 auto called_cb = [&called](int32_t result) { called = true; }; | 266 base::RunLoop run_loop; |
| 267 auto called_cb = [&called, &run_loop](int32_t result) { |
| 268 called = true; |
| 269 run_loop.Quit(); |
| 270 }; |
| 231 sample::ServicePtr ptr; | 271 sample::ServicePtr ptr; |
| 232 auto request = GetProxy(&ptr); | 272 auto request = GetProxy(&ptr); |
| 233 ServiceImpl impl; | 273 ServiceImpl impl; |
| 234 Binding<sample::Service> binding(&impl, std::move(request)); | 274 Binding<sample::Service> binding(&impl, std::move(request)); |
| 235 binding.PauseIncomingMethodCallProcessing(); | 275 binding.PauseIncomingMethodCallProcessing(); |
| 236 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 276 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 237 called_cb); | 277 called_cb); |
| 238 EXPECT_FALSE(called); | 278 EXPECT_FALSE(called); |
| 239 loop().RunUntilIdle(); | 279 loop().RunUntilIdle(); |
| 240 // Frobinate() should not be called as the binding is paused. | 280 // Frobinate() should not be called as the binding is paused. |
| 241 EXPECT_FALSE(called); | 281 EXPECT_FALSE(called); |
| 242 | 282 |
| 243 // Resume the binding, which should trigger processing. | 283 // Resume the binding, which should trigger processing. |
| 244 binding.ResumeIncomingMethodCallProcessing(); | 284 binding.ResumeIncomingMethodCallProcessing(); |
| 245 loop().RunUntilIdle(); | 285 run_loop.Run(); |
| 246 EXPECT_TRUE(called); | 286 EXPECT_TRUE(called); |
| 247 } | 287 } |
| 248 | 288 |
| 249 // Verifies the connection error handler is not run while a binding is paused. | 289 // Verifies the connection error handler is not run while a binding is paused. |
| 250 TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { | 290 TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { |
| 251 bool called = false; | 291 bool called = false; |
| 292 base::RunLoop run_loop; |
| 252 sample::ServicePtr ptr; | 293 sample::ServicePtr ptr; |
| 253 auto request = GetProxy(&ptr); | 294 auto request = GetProxy(&ptr); |
| 254 ServiceImpl impl; | 295 ServiceImpl impl; |
| 255 Binding<sample::Service> binding(&impl, std::move(request)); | 296 Binding<sample::Service> binding(&impl, std::move(request)); |
| 256 binding.set_connection_error_handler([&called]() { called = true; }); | 297 binding.set_connection_error_handler([&called, &run_loop]() { |
| 298 called = true; |
| 299 run_loop.Quit(); |
| 300 }); |
| 257 binding.PauseIncomingMethodCallProcessing(); | 301 binding.PauseIncomingMethodCallProcessing(); |
| 258 | 302 |
| 259 ptr.reset(); | 303 ptr.reset(); |
| 260 loop().RunUntilIdle(); | 304 loop().RunUntilIdle(); |
| 261 // The connection error handle should not be called as the binding is paused. | 305 // The connection error handle should not be called as the binding is paused. |
| 262 EXPECT_FALSE(called); | 306 EXPECT_FALSE(called); |
| 263 | 307 |
| 264 // Resume the binding, which should trigger the error handler. | 308 // Resume the binding, which should trigger the error handler. |
| 265 binding.ResumeIncomingMethodCallProcessing(); | 309 binding.ResumeIncomingMethodCallProcessing(); |
| 266 loop().RunUntilIdle(); | 310 run_loop.Run(); |
| 267 EXPECT_TRUE(called); | 311 EXPECT_TRUE(called); |
| 268 } | 312 } |
| 269 | 313 |
| 270 // StrongBindingTest ----------------------------------------------------------- | 314 // StrongBindingTest ----------------------------------------------------------- |
| 271 | 315 |
| 272 using StrongBindingTest = BindingTestBase; | 316 using StrongBindingTest = BindingTestBase; |
| 273 | 317 |
| 274 // Tests that destroying a mojo::StrongBinding closes the bound message pipe | 318 // Tests that destroying a mojo::StrongBinding closes the bound message pipe |
| 275 // handle but does *not* destroy the implementation object. | 319 // handle but does *not* destroy the implementation object. |
| 276 TEST_F(StrongBindingTest, DestroyClosesMessagePipe) { | 320 TEST_F(StrongBindingTest, DestroyClosesMessagePipe) { |
| 321 base::RunLoop run_loop; |
| 277 bool encountered_error = false; | 322 bool encountered_error = false; |
| 278 bool was_deleted = false; | 323 bool was_deleted = false; |
| 279 ServiceImpl impl(&was_deleted); | 324 ServiceImpl impl(&was_deleted); |
| 280 sample::ServicePtr ptr; | 325 sample::ServicePtr ptr; |
| 281 auto request = GetProxy(&ptr); | 326 auto request = GetProxy(&ptr); |
| 282 ptr.set_connection_error_handler( | 327 ptr.set_connection_error_handler( |
| 283 [&encountered_error]() { encountered_error = true; }); | 328 [&encountered_error, &run_loop]() { |
| 329 encountered_error = true; |
| 330 run_loop.Quit(); |
| 331 }); |
| 284 bool called = false; | 332 bool called = false; |
| 285 auto called_cb = [&called](int32_t result) { called = true; }; | 333 base::RunLoop run_loop2; |
| 334 auto called_cb = [&called, &run_loop2](int32_t result) { |
| 335 called = true; |
| 336 run_loop2.Quit(); |
| 337 }; |
| 286 { | 338 { |
| 287 StrongBinding<sample::Service> binding(&impl, std::move(request)); | 339 StrongBinding<sample::Service> binding(&impl, std::move(request)); |
| 288 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 340 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 289 called_cb); | 341 called_cb); |
| 290 loop().RunUntilIdle(); | 342 run_loop2.Run(); |
| 291 EXPECT_TRUE(called); | 343 EXPECT_TRUE(called); |
| 292 EXPECT_FALSE(encountered_error); | 344 EXPECT_FALSE(encountered_error); |
| 293 } | 345 } |
| 294 // Now that the StrongBinding is out of scope we should detect an error on the | 346 // Now that the StrongBinding is out of scope we should detect an error on the |
| 295 // other end of the pipe. | 347 // other end of the pipe. |
| 296 loop().RunUntilIdle(); | 348 run_loop.Run(); |
| 297 EXPECT_TRUE(encountered_error); | 349 EXPECT_TRUE(encountered_error); |
| 298 // But destroying the StrongBinding doesn't destroy the object. | 350 // But destroying the StrongBinding doesn't destroy the object. |
| 299 ASSERT_FALSE(was_deleted); | 351 ASSERT_FALSE(was_deleted); |
| 300 } | 352 } |
| 301 | 353 |
| 302 class ServiceImplWithStrongBinding : public ServiceImpl { | 354 class ServiceImplWithStrongBinding : public ServiceImpl { |
| 303 public: | 355 public: |
| 304 ServiceImplWithStrongBinding(bool* was_deleted, | 356 ServiceImplWithStrongBinding(bool* was_deleted, |
| 305 InterfaceRequest<sample::Service> request) | 357 InterfaceRequest<sample::Service> request) |
| 306 : ServiceImpl(was_deleted), binding_(this, std::move(request)) {} | 358 : ServiceImpl(was_deleted), binding_(this, std::move(request)) {} |
| 307 | 359 |
| 308 StrongBinding<sample::Service>& binding() { return binding_; } | 360 StrongBinding<sample::Service>& binding() { return binding_; } |
| 309 | 361 |
| 310 private: | 362 private: |
| 311 StrongBinding<sample::Service> binding_; | 363 StrongBinding<sample::Service> binding_; |
| 312 | 364 |
| 313 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding); | 365 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding); |
| 314 }; | 366 }; |
| 315 | 367 |
| 316 // Tests the typical case, where the implementation object owns the | 368 // Tests the typical case, where the implementation object owns the |
| 317 // StrongBinding (and should be destroyed on connection error). | 369 // StrongBinding (and should be destroyed on connection error). |
| 318 TEST_F(StrongBindingTest, ConnectionErrorDestroysImpl) { | 370 TEST_F(StrongBindingTest, ConnectionErrorDestroysImpl) { |
| 319 sample::ServicePtr ptr; | 371 sample::ServicePtr ptr; |
| 320 bool was_deleted = false; | 372 bool was_deleted = false; |
| 321 // Will delete itself. | 373 // Will delete itself. |
| 322 new ServiceImplWithBinding(&was_deleted, GetProxy(&ptr)); | 374 base::RunLoop run_loop; |
| 375 new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(), |
| 376 GetProxy(&ptr)); |
| 323 | 377 |
| 324 loop().RunUntilIdle(); | 378 loop().RunUntilIdle(); |
| 325 EXPECT_FALSE(was_deleted); | 379 EXPECT_FALSE(was_deleted); |
| 326 | 380 |
| 327 ptr.reset(); | 381 ptr.reset(); |
| 328 EXPECT_FALSE(was_deleted); | 382 EXPECT_FALSE(was_deleted); |
| 329 loop().RunUntilIdle(); | 383 run_loop.Run(); |
| 330 EXPECT_TRUE(was_deleted); | 384 EXPECT_TRUE(was_deleted); |
| 331 } | 385 } |
| 332 | 386 |
| 333 // Tests that even when the implementation object owns the StrongBinding, that | 387 // Tests that even when the implementation object owns the StrongBinding, that |
| 334 // the implementation can still be deleted (which should result in the message | 388 // the implementation can still be deleted (which should result in the message |
| 335 // pipe being closed). Also checks that the connection error handler doesn't get | 389 // pipe being closed). Also checks that the connection error handler doesn't get |
| 336 // called. | 390 // called. |
| 337 TEST_F(StrongBindingTest, ExplicitDeleteImpl) { | 391 TEST_F(StrongBindingTest, ExplicitDeleteImpl) { |
| 338 bool ptr_error_handler_called = false; | 392 bool ptr_error_handler_called = false; |
| 339 sample::ServicePtr ptr; | 393 sample::ServicePtr ptr; |
| 340 auto request = GetProxy(&ptr); | 394 auto request = GetProxy(&ptr); |
| 395 base::RunLoop run_loop; |
| 341 ptr.set_connection_error_handler( | 396 ptr.set_connection_error_handler( |
| 342 [&ptr_error_handler_called]() { ptr_error_handler_called = true; }); | 397 [&ptr_error_handler_called, &run_loop]() { |
| 398 ptr_error_handler_called = true; |
| 399 run_loop.Quit(); |
| 400 }); |
| 343 bool was_deleted = false; | 401 bool was_deleted = false; |
| 344 ServiceImplWithStrongBinding* impl = | 402 ServiceImplWithStrongBinding* impl = |
| 345 new ServiceImplWithStrongBinding(&was_deleted, std::move(request)); | 403 new ServiceImplWithStrongBinding(&was_deleted, std::move(request)); |
| 346 bool binding_error_handler_called = false; | 404 bool binding_error_handler_called = false; |
| 347 impl->binding().set_connection_error_handler( | 405 impl->binding().set_connection_error_handler( |
| 348 [&binding_error_handler_called]() { | 406 [&binding_error_handler_called]() { |
| 349 binding_error_handler_called = true; | 407 binding_error_handler_called = true; |
| 350 }); | 408 }); |
| 351 | 409 |
| 352 loop().RunUntilIdle(); | 410 loop().RunUntilIdle(); |
| 353 EXPECT_FALSE(ptr_error_handler_called); | 411 EXPECT_FALSE(ptr_error_handler_called); |
| 354 EXPECT_FALSE(was_deleted); | 412 EXPECT_FALSE(was_deleted); |
| 355 | 413 |
| 356 delete impl; | 414 delete impl; |
| 357 EXPECT_FALSE(ptr_error_handler_called); | 415 EXPECT_FALSE(ptr_error_handler_called); |
| 358 EXPECT_TRUE(was_deleted); | 416 EXPECT_TRUE(was_deleted); |
| 359 was_deleted = false; // It shouldn't be double-deleted! | 417 was_deleted = false; // It shouldn't be double-deleted! |
| 360 loop().RunUntilIdle(); | 418 run_loop.Run(); |
| 361 EXPECT_TRUE(ptr_error_handler_called); | 419 EXPECT_TRUE(ptr_error_handler_called); |
| 362 EXPECT_FALSE(was_deleted); | 420 EXPECT_FALSE(was_deleted); |
| 363 | 421 |
| 364 EXPECT_FALSE(binding_error_handler_called); | 422 EXPECT_FALSE(binding_error_handler_called); |
| 365 } | 423 } |
| 366 | 424 |
| 367 } // namespace | 425 } // namespace |
| 368 } // mojo | 426 } // mojo |
| OLD | NEW |