| 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" |
| 9 |
| 8 #include <stdint.h> | 10 #include <stdint.h> |
| 11 #include <utility> |
| 9 | 12 |
| 10 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 11 #include "mojo/message_pump/message_pump_mojo.h" | 14 #include "mojo/message_pump/message_pump_mojo.h" |
| 12 #include "mojo/public/cpp/bindings/binding.h" | |
| 13 #include "mojo/public/cpp/bindings/strong_binding.h" | 15 #include "mojo/public/cpp/bindings/strong_binding.h" |
| 14 #include "mojo/public/cpp/system/macros.h" | 16 #include "mojo/public/cpp/system/macros.h" |
| 15 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" | 17 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" |
| 16 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" | 18 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 20 |
| 19 namespace mojo { | 21 namespace mojo { |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 class BindingTestBase : public testing::Test { | 24 class BindingTestBase : public testing::Test { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 // BindingTest ----------------------------------------------------------------- | 61 // BindingTest ----------------------------------------------------------------- |
| 60 | 62 |
| 61 using BindingTest = BindingTestBase; | 63 using BindingTest = BindingTestBase; |
| 62 | 64 |
| 63 TEST_F(BindingTest, Close) { | 65 TEST_F(BindingTest, Close) { |
| 64 bool called = false; | 66 bool called = false; |
| 65 sample::ServicePtr ptr; | 67 sample::ServicePtr ptr; |
| 66 auto request = GetProxy(&ptr); | 68 auto request = GetProxy(&ptr); |
| 67 ptr.set_connection_error_handler([&called]() { called = true; }); | 69 ptr.set_connection_error_handler([&called]() { called = true; }); |
| 68 ServiceImpl impl; | 70 ServiceImpl impl; |
| 69 Binding<sample::Service> binding(&impl, request.Pass()); | 71 Binding<sample::Service> binding(&impl, std::move(request)); |
| 70 | 72 |
| 71 binding.Close(); | 73 binding.Close(); |
| 72 EXPECT_FALSE(called); | 74 EXPECT_FALSE(called); |
| 73 loop().RunUntilIdle(); | 75 loop().RunUntilIdle(); |
| 74 EXPECT_TRUE(called); | 76 EXPECT_TRUE(called); |
| 75 } | 77 } |
| 76 | 78 |
| 77 // Tests that destroying a mojo::Binding closes the bound message pipe handle. | 79 // Tests that destroying a mojo::Binding closes the bound message pipe handle. |
| 78 TEST_F(BindingTest, DestroyClosesMessagePipe) { | 80 TEST_F(BindingTest, DestroyClosesMessagePipe) { |
| 79 bool encountered_error = false; | 81 bool encountered_error = false; |
| 80 ServiceImpl impl; | 82 ServiceImpl impl; |
| 81 sample::ServicePtr ptr; | 83 sample::ServicePtr ptr; |
| 82 auto request = GetProxy(&ptr); | 84 auto request = GetProxy(&ptr); |
| 83 ptr.set_connection_error_handler( | 85 ptr.set_connection_error_handler( |
| 84 [&encountered_error]() { encountered_error = true; }); | 86 [&encountered_error]() { encountered_error = true; }); |
| 85 bool called = false; | 87 bool called = false; |
| 86 auto called_cb = [&called](int32_t result) { called = true; }; | 88 auto called_cb = [&called](int32_t result) { called = true; }; |
| 87 { | 89 { |
| 88 Binding<sample::Service> binding(&impl, request.Pass()); | 90 Binding<sample::Service> binding(&impl, std::move(request)); |
| 89 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 91 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 90 called_cb); | 92 called_cb); |
| 91 loop().RunUntilIdle(); | 93 loop().RunUntilIdle(); |
| 92 EXPECT_TRUE(called); | 94 EXPECT_TRUE(called); |
| 93 EXPECT_FALSE(encountered_error); | 95 EXPECT_FALSE(encountered_error); |
| 94 } | 96 } |
| 95 // Now that the Binding is out of scope we should detect an error on the other | 97 // Now that the Binding is out of scope we should detect an error on the other |
| 96 // end of the pipe. | 98 // end of the pipe. |
| 97 loop().RunUntilIdle(); | 99 loop().RunUntilIdle(); |
| 98 EXPECT_TRUE(encountered_error); | 100 EXPECT_TRUE(encountered_error); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 // called. | 142 // called. |
| 141 ptr.reset(); | 143 ptr.reset(); |
| 142 loop().RunUntilIdle(); | 144 loop().RunUntilIdle(); |
| 143 EXPECT_FALSE(called); | 145 EXPECT_FALSE(called); |
| 144 } | 146 } |
| 145 | 147 |
| 146 class ServiceImplWithBinding : public ServiceImpl { | 148 class ServiceImplWithBinding : public ServiceImpl { |
| 147 public: | 149 public: |
| 148 ServiceImplWithBinding(bool* was_deleted, | 150 ServiceImplWithBinding(bool* was_deleted, |
| 149 InterfaceRequest<sample::Service> request) | 151 InterfaceRequest<sample::Service> request) |
| 150 : ServiceImpl(was_deleted), binding_(this, request.Pass()) { | 152 : ServiceImpl(was_deleted), binding_(this, std::move(request)) { |
| 151 binding_.set_connection_error_handler([this]() { delete this; }); | 153 binding_.set_connection_error_handler([this]() { delete this; }); |
| 152 } | 154 } |
| 153 | 155 |
| 154 private: | 156 private: |
| 155 Binding<sample::Service> binding_; | 157 Binding<sample::Service> binding_; |
| 156 | 158 |
| 157 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); | 159 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding); |
| 158 }; | 160 }; |
| 159 | 161 |
| 160 // Tests that the binding may be deleted in the connection error handler. | 162 // Tests that the binding may be deleted in the connection error handler. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 185 called = false; | 187 called = false; |
| 186 auto request = binding.Unbind(); | 188 auto request = binding.Unbind(); |
| 187 EXPECT_FALSE(binding.is_bound()); | 189 EXPECT_FALSE(binding.is_bound()); |
| 188 // All calls should fail when not bound... | 190 // All calls should fail when not bound... |
| 189 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 191 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 190 called_cb); | 192 called_cb); |
| 191 loop().RunUntilIdle(); | 193 loop().RunUntilIdle(); |
| 192 EXPECT_FALSE(called); | 194 EXPECT_FALSE(called); |
| 193 | 195 |
| 194 called = false; | 196 called = false; |
| 195 binding.Bind(request.Pass()); | 197 binding.Bind(std::move(request)); |
| 196 EXPECT_TRUE(binding.is_bound()); | 198 EXPECT_TRUE(binding.is_bound()); |
| 197 // ...and should succeed again when the rebound. | 199 // ...and should succeed again when the rebound. |
| 198 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 200 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 199 called_cb); | 201 called_cb); |
| 200 loop().RunUntilIdle(); | 202 loop().RunUntilIdle(); |
| 201 EXPECT_TRUE(called); | 203 EXPECT_TRUE(called); |
| 202 } | 204 } |
| 203 | 205 |
| 204 class IntegerAccessorImpl : public sample::IntegerAccessor { | 206 class IntegerAccessorImpl : public sample::IntegerAccessor { |
| 205 public: | 207 public: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 222 Binding<sample::IntegerAccessor> binding(&impl, &ptr); | 224 Binding<sample::IntegerAccessor> binding(&impl, &ptr); |
| 223 EXPECT_EQ(3u, ptr.version()); | 225 EXPECT_EQ(3u, ptr.version()); |
| 224 } | 226 } |
| 225 | 227 |
| 226 TEST_F(BindingTest, PauseResume) { | 228 TEST_F(BindingTest, PauseResume) { |
| 227 bool called = false; | 229 bool called = false; |
| 228 auto called_cb = [&called](int32_t result) { called = true; }; | 230 auto called_cb = [&called](int32_t result) { called = true; }; |
| 229 sample::ServicePtr ptr; | 231 sample::ServicePtr ptr; |
| 230 auto request = GetProxy(&ptr); | 232 auto request = GetProxy(&ptr); |
| 231 ServiceImpl impl; | 233 ServiceImpl impl; |
| 232 Binding<sample::Service> binding(&impl, request.Pass()); | 234 Binding<sample::Service> binding(&impl, std::move(request)); |
| 233 binding.PauseIncomingMethodCallProcessing(); | 235 binding.PauseIncomingMethodCallProcessing(); |
| 234 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 236 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 235 called_cb); | 237 called_cb); |
| 236 EXPECT_FALSE(called); | 238 EXPECT_FALSE(called); |
| 237 loop().RunUntilIdle(); | 239 loop().RunUntilIdle(); |
| 238 // Frobinate() should not be called as the binding is paused. | 240 // Frobinate() should not be called as the binding is paused. |
| 239 EXPECT_FALSE(called); | 241 EXPECT_FALSE(called); |
| 240 | 242 |
| 241 // Resume the binding, which should trigger processing. | 243 // Resume the binding, which should trigger processing. |
| 242 binding.ResumeIncomingMethodCallProcessing(); | 244 binding.ResumeIncomingMethodCallProcessing(); |
| 243 loop().RunUntilIdle(); | 245 loop().RunUntilIdle(); |
| 244 EXPECT_TRUE(called); | 246 EXPECT_TRUE(called); |
| 245 } | 247 } |
| 246 | 248 |
| 247 // Verifies the connection error handler is not run while a binding is paused. | 249 // Verifies the connection error handler is not run while a binding is paused. |
| 248 TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { | 250 TEST_F(BindingTest, ErrorHandleNotRunWhilePaused) { |
| 249 bool called = false; | 251 bool called = false; |
| 250 sample::ServicePtr ptr; | 252 sample::ServicePtr ptr; |
| 251 auto request = GetProxy(&ptr); | 253 auto request = GetProxy(&ptr); |
| 252 ServiceImpl impl; | 254 ServiceImpl impl; |
| 253 Binding<sample::Service> binding(&impl, request.Pass()); | 255 Binding<sample::Service> binding(&impl, std::move(request)); |
| 254 binding.set_connection_error_handler([&called]() { called = true; }); | 256 binding.set_connection_error_handler([&called]() { called = true; }); |
| 255 binding.PauseIncomingMethodCallProcessing(); | 257 binding.PauseIncomingMethodCallProcessing(); |
| 256 | 258 |
| 257 ptr.reset(); | 259 ptr.reset(); |
| 258 loop().RunUntilIdle(); | 260 loop().RunUntilIdle(); |
| 259 // The connection error handle should not be called as the binding is paused. | 261 // The connection error handle should not be called as the binding is paused. |
| 260 EXPECT_FALSE(called); | 262 EXPECT_FALSE(called); |
| 261 | 263 |
| 262 // Resume the binding, which should trigger the error handler. | 264 // Resume the binding, which should trigger the error handler. |
| 263 binding.ResumeIncomingMethodCallProcessing(); | 265 binding.ResumeIncomingMethodCallProcessing(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 275 bool encountered_error = false; | 277 bool encountered_error = false; |
| 276 bool was_deleted = false; | 278 bool was_deleted = false; |
| 277 ServiceImpl impl(&was_deleted); | 279 ServiceImpl impl(&was_deleted); |
| 278 sample::ServicePtr ptr; | 280 sample::ServicePtr ptr; |
| 279 auto request = GetProxy(&ptr); | 281 auto request = GetProxy(&ptr); |
| 280 ptr.set_connection_error_handler( | 282 ptr.set_connection_error_handler( |
| 281 [&encountered_error]() { encountered_error = true; }); | 283 [&encountered_error]() { encountered_error = true; }); |
| 282 bool called = false; | 284 bool called = false; |
| 283 auto called_cb = [&called](int32_t result) { called = true; }; | 285 auto called_cb = [&called](int32_t result) { called = true; }; |
| 284 { | 286 { |
| 285 StrongBinding<sample::Service> binding(&impl, request.Pass()); | 287 StrongBinding<sample::Service> binding(&impl, std::move(request)); |
| 286 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, | 288 ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
| 287 called_cb); | 289 called_cb); |
| 288 loop().RunUntilIdle(); | 290 loop().RunUntilIdle(); |
| 289 EXPECT_TRUE(called); | 291 EXPECT_TRUE(called); |
| 290 EXPECT_FALSE(encountered_error); | 292 EXPECT_FALSE(encountered_error); |
| 291 } | 293 } |
| 292 // Now that the StrongBinding is out of scope we should detect an error on the | 294 // Now that the StrongBinding is out of scope we should detect an error on the |
| 293 // other end of the pipe. | 295 // other end of the pipe. |
| 294 loop().RunUntilIdle(); | 296 loop().RunUntilIdle(); |
| 295 EXPECT_TRUE(encountered_error); | 297 EXPECT_TRUE(encountered_error); |
| 296 // But destroying the StrongBinding doesn't destroy the object. | 298 // But destroying the StrongBinding doesn't destroy the object. |
| 297 ASSERT_FALSE(was_deleted); | 299 ASSERT_FALSE(was_deleted); |
| 298 } | 300 } |
| 299 | 301 |
| 300 class ServiceImplWithStrongBinding : public ServiceImpl { | 302 class ServiceImplWithStrongBinding : public ServiceImpl { |
| 301 public: | 303 public: |
| 302 ServiceImplWithStrongBinding(bool* was_deleted, | 304 ServiceImplWithStrongBinding(bool* was_deleted, |
| 303 InterfaceRequest<sample::Service> request) | 305 InterfaceRequest<sample::Service> request) |
| 304 : ServiceImpl(was_deleted), binding_(this, request.Pass()) {} | 306 : ServiceImpl(was_deleted), binding_(this, std::move(request)) {} |
| 305 | 307 |
| 306 StrongBinding<sample::Service>& binding() { return binding_; } | 308 StrongBinding<sample::Service>& binding() { return binding_; } |
| 307 | 309 |
| 308 private: | 310 private: |
| 309 StrongBinding<sample::Service> binding_; | 311 StrongBinding<sample::Service> binding_; |
| 310 | 312 |
| 311 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding); | 313 MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceImplWithStrongBinding); |
| 312 }; | 314 }; |
| 313 | 315 |
| 314 // Tests the typical case, where the implementation object owns the | 316 // Tests the typical case, where the implementation object owns the |
| (...skipping 18 matching lines...) Expand all Loading... |
| 333 // pipe being closed). Also checks that the connection error handler doesn't get | 335 // pipe being closed). Also checks that the connection error handler doesn't get |
| 334 // called. | 336 // called. |
| 335 TEST_F(StrongBindingTest, ExplicitDeleteImpl) { | 337 TEST_F(StrongBindingTest, ExplicitDeleteImpl) { |
| 336 bool ptr_error_handler_called = false; | 338 bool ptr_error_handler_called = false; |
| 337 sample::ServicePtr ptr; | 339 sample::ServicePtr ptr; |
| 338 auto request = GetProxy(&ptr); | 340 auto request = GetProxy(&ptr); |
| 339 ptr.set_connection_error_handler( | 341 ptr.set_connection_error_handler( |
| 340 [&ptr_error_handler_called]() { ptr_error_handler_called = true; }); | 342 [&ptr_error_handler_called]() { ptr_error_handler_called = true; }); |
| 341 bool was_deleted = false; | 343 bool was_deleted = false; |
| 342 ServiceImplWithStrongBinding* impl = | 344 ServiceImplWithStrongBinding* impl = |
| 343 new ServiceImplWithStrongBinding(&was_deleted, request.Pass()); | 345 new ServiceImplWithStrongBinding(&was_deleted, std::move(request)); |
| 344 bool binding_error_handler_called = false; | 346 bool binding_error_handler_called = false; |
| 345 impl->binding().set_connection_error_handler( | 347 impl->binding().set_connection_error_handler( |
| 346 [&binding_error_handler_called]() { | 348 [&binding_error_handler_called]() { |
| 347 binding_error_handler_called = true; | 349 binding_error_handler_called = true; |
| 348 }); | 350 }); |
| 349 | 351 |
| 350 loop().RunUntilIdle(); | 352 loop().RunUntilIdle(); |
| 351 EXPECT_FALSE(ptr_error_handler_called); | 353 EXPECT_FALSE(ptr_error_handler_called); |
| 352 EXPECT_FALSE(was_deleted); | 354 EXPECT_FALSE(was_deleted); |
| 353 | 355 |
| 354 delete impl; | 356 delete impl; |
| 355 EXPECT_FALSE(ptr_error_handler_called); | 357 EXPECT_FALSE(ptr_error_handler_called); |
| 356 EXPECT_TRUE(was_deleted); | 358 EXPECT_TRUE(was_deleted); |
| 357 was_deleted = false; // It shouldn't be double-deleted! | 359 was_deleted = false; // It shouldn't be double-deleted! |
| 358 loop().RunUntilIdle(); | 360 loop().RunUntilIdle(); |
| 359 EXPECT_TRUE(ptr_error_handler_called); | 361 EXPECT_TRUE(ptr_error_handler_called); |
| 360 EXPECT_FALSE(was_deleted); | 362 EXPECT_FALSE(was_deleted); |
| 361 | 363 |
| 362 EXPECT_FALSE(binding_error_handler_called); | 364 EXPECT_FALSE(binding_error_handler_called); |
| 363 } | 365 } |
| 364 | 366 |
| 365 } // namespace | 367 } // namespace |
| 366 } // mojo | 368 } // mojo |
| OLD | NEW |