| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "mojo/public/cpp/bindings/binding.h" | |
| 6 #include "mojo/public/cpp/bindings/error_handler.h" | 5 #include "mojo/public/cpp/bindings/error_handler.h" |
| 7 #include "mojo/public/cpp/bindings/strong_binding.h" | |
| 8 #include "mojo/public/cpp/environment/environment.h" | 6 #include "mojo/public/cpp/environment/environment.h" |
| 9 #include "mojo/public/cpp/utility/run_loop.h" | 7 #include "mojo/public/cpp/utility/run_loop.h" |
| 10 #include "mojo/public/interfaces/bindings/tests/math_calculator.mojom.h" | 8 #include "mojo/public/interfaces/bindings/tests/math_calculator.mojom.h" |
| 11 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" | 9 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 11 |
| 14 namespace mojo { | 12 namespace mojo { |
| 15 namespace test { | 13 namespace test { |
| 16 namespace { | 14 namespace { |
| 17 | 15 |
| 18 class ErrorObserver : public ErrorHandler { | 16 class ErrorObserver : public ErrorHandler { |
| 19 public: | 17 public: |
| 20 ErrorObserver() : encountered_error_(false) {} | 18 ErrorObserver() : encountered_error_(false) {} |
| 21 | 19 |
| 22 bool encountered_error() const { return encountered_error_; } | 20 bool encountered_error() const { return encountered_error_; } |
| 23 | 21 |
| 24 void OnConnectionError() override { encountered_error_ = true; } | 22 void OnConnectionError() override { encountered_error_ = true; } |
| 25 | 23 |
| 26 private: | 24 private: |
| 27 bool encountered_error_; | 25 bool encountered_error_; |
| 28 }; | 26 }; |
| 29 | 27 |
| 30 class MathCalculatorImpl : public InterfaceImpl<math::Calculator> { | 28 class MathCalculatorImpl : public InterfaceImpl<math::Calculator> { |
| 31 public: | 29 public: |
| 32 ~MathCalculatorImpl() override {} | 30 ~MathCalculatorImpl() override {} |
| 33 | 31 |
| 34 MathCalculatorImpl() : total_(0.0) {} | 32 MathCalculatorImpl() : total_(0.0), got_connection_(false) {} |
| 33 |
| 34 void OnConnectionEstablished() override { got_connection_ = true; } |
| 35 | 35 |
| 36 void Clear() override { client()->Output(total_); } | 36 void Clear() override { client()->Output(total_); } |
| 37 | 37 |
| 38 void Add(double value) override { | 38 void Add(double value) override { |
| 39 total_ += value; | 39 total_ += value; |
| 40 client()->Output(total_); | 40 client()->Output(total_); |
| 41 } | 41 } |
| 42 | 42 |
| 43 void Multiply(double value) override { | 43 void Multiply(double value) override { |
| 44 total_ *= value; | 44 total_ *= value; |
| 45 client()->Output(total_); | 45 client()->Output(total_); |
| 46 } | 46 } |
| 47 | 47 |
| 48 bool got_connection() const { return got_connection_; } |
| 49 |
| 48 private: | 50 private: |
| 49 double total_; | 51 double total_; |
| 52 bool got_connection_; |
| 50 }; | 53 }; |
| 51 | 54 |
| 52 class MathCalculatorUIImpl : public math::CalculatorUI { | 55 class MathCalculatorUIImpl : public math::CalculatorUI { |
| 53 public: | 56 public: |
| 54 explicit MathCalculatorUIImpl(math::CalculatorPtr calculator) | 57 explicit MathCalculatorUIImpl(math::CalculatorPtr calculator) |
| 55 : calculator_(calculator.Pass()), output_(0.0) { | 58 : calculator_(calculator.Pass()), output_(0.0) { |
| 56 calculator_.set_client(this); | 59 calculator_.set_client(this); |
| 57 } | 60 } |
| 58 | 61 |
| 59 bool WaitForIncomingMethodCall() { | 62 bool WaitForIncomingMethodCall() { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 static int num_instances_; | 116 static int num_instances_; |
| 114 }; | 117 }; |
| 115 | 118 |
| 116 // static | 119 // static |
| 117 int SelfDestructingMathCalculatorUIImpl::num_instances_ = 0; | 120 int SelfDestructingMathCalculatorUIImpl::num_instances_ = 0; |
| 118 | 121 |
| 119 class ReentrantServiceImpl : public InterfaceImpl<sample::Service> { | 122 class ReentrantServiceImpl : public InterfaceImpl<sample::Service> { |
| 120 public: | 123 public: |
| 121 ~ReentrantServiceImpl() override {} | 124 ~ReentrantServiceImpl() override {} |
| 122 | 125 |
| 123 ReentrantServiceImpl() : call_depth_(0), max_call_depth_(0) {} | 126 ReentrantServiceImpl() |
| 127 : got_connection_(false), call_depth_(0), max_call_depth_(0) {} |
| 128 |
| 129 void OnConnectionEstablished() override { got_connection_ = true; } |
| 130 |
| 131 bool got_connection() const { return got_connection_; } |
| 124 | 132 |
| 125 int max_call_depth() { return max_call_depth_; } | 133 int max_call_depth() { return max_call_depth_; } |
| 126 | 134 |
| 127 void Frobinate(sample::FooPtr foo, | 135 void Frobinate(sample::FooPtr foo, |
| 128 sample::Service::BazOptions baz, | 136 sample::Service::BazOptions baz, |
| 129 sample::PortPtr port) override { | 137 sample::PortPtr port) override { |
| 130 max_call_depth_ = std::max(++call_depth_, max_call_depth_); | 138 max_call_depth_ = std::max(++call_depth_, max_call_depth_); |
| 131 if (call_depth_ == 1) { | 139 if (call_depth_ == 1) { |
| 132 EXPECT_TRUE(WaitForIncomingMethodCall()); | 140 EXPECT_TRUE(WaitForIncomingMethodCall()); |
| 133 } | 141 } |
| 134 call_depth_--; | 142 call_depth_--; |
| 135 } | 143 } |
| 136 | 144 |
| 137 void GetPort(mojo::InterfaceRequest<sample::Port> port) override {} | 145 void GetPort(mojo::InterfaceRequest<sample::Port> port) override {} |
| 138 | 146 |
| 139 private: | 147 private: |
| 148 bool got_connection_; |
| 140 int call_depth_; | 149 int call_depth_; |
| 141 int max_call_depth_; | 150 int max_call_depth_; |
| 142 }; | 151 }; |
| 143 | 152 |
| 144 class InterfacePtrTest : public testing::Test { | 153 class InterfacePtrTest : public testing::Test { |
| 145 public: | 154 public: |
| 146 ~InterfacePtrTest() override { loop_.RunUntilIdle(); } | 155 ~InterfacePtrTest() override { loop_.RunUntilIdle(); } |
| 147 | 156 |
| 148 void PumpMessages() { loop_.RunUntilIdle(); } | 157 void PumpMessages() { loop_.RunUntilIdle(); } |
| 149 | 158 |
| 150 private: | 159 private: |
| 151 Environment env_; | 160 Environment env_; |
| 152 RunLoop loop_; | 161 RunLoop loop_; |
| 153 }; | 162 }; |
| 154 | 163 |
| 155 TEST_F(InterfacePtrTest, EndToEnd) { | 164 TEST_F(InterfacePtrTest, EndToEnd) { |
| 156 math::CalculatorPtr calc; | 165 math::CalculatorPtr calc; |
| 157 BindToProxy(new MathCalculatorImpl(), &calc); | 166 MathCalculatorImpl* impl = BindToProxy(new MathCalculatorImpl(), &calc); |
| 167 EXPECT_TRUE(impl->got_connection()); |
| 158 | 168 |
| 159 // Suppose this is instantiated in a process that has pipe1_. | 169 // Suppose this is instantiated in a process that has pipe1_. |
| 160 MathCalculatorUIImpl calculator_ui(calc.Pass()); | 170 MathCalculatorUIImpl calculator_ui(calc.Pass()); |
| 161 | 171 |
| 162 calculator_ui.Add(2.0); | 172 calculator_ui.Add(2.0); |
| 163 calculator_ui.Multiply(5.0); | 173 calculator_ui.Multiply(5.0); |
| 164 | 174 |
| 165 PumpMessages(); | 175 PumpMessages(); |
| 166 | 176 |
| 167 EXPECT_EQ(10.0, calculator_ui.GetOutput()); | 177 EXPECT_EQ(10.0, calculator_ui.GetOutput()); |
| 168 } | 178 } |
| 169 | 179 |
| 170 TEST_F(InterfacePtrTest, EndToEnd_Synchronous) { | 180 TEST_F(InterfacePtrTest, EndToEnd_Synchronous) { |
| 171 math::CalculatorPtr calc; | 181 math::CalculatorPtr calc; |
| 172 MathCalculatorImpl* impl = BindToProxy(new MathCalculatorImpl(), &calc); | 182 MathCalculatorImpl* impl = BindToProxy(new MathCalculatorImpl(), &calc); |
| 183 EXPECT_TRUE(impl->got_connection()); |
| 173 | 184 |
| 174 // Suppose this is instantiated in a process that has pipe1_. | 185 // Suppose this is instantiated in a process that has pipe1_. |
| 175 MathCalculatorUIImpl calculator_ui(calc.Pass()); | 186 MathCalculatorUIImpl calculator_ui(calc.Pass()); |
| 176 | 187 |
| 177 EXPECT_EQ(0.0, calculator_ui.GetOutput()); | 188 EXPECT_EQ(0.0, calculator_ui.GetOutput()); |
| 178 | 189 |
| 179 calculator_ui.Add(2.0); | 190 calculator_ui.Add(2.0); |
| 180 EXPECT_EQ(0.0, calculator_ui.GetOutput()); | 191 EXPECT_EQ(0.0, calculator_ui.GetOutput()); |
| 181 impl->WaitForIncomingMethodCall(); | 192 impl->WaitForIncomingMethodCall(); |
| 182 calculator_ui.WaitForIncomingMethodCall(); | 193 calculator_ui.WaitForIncomingMethodCall(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 245 |
| 235 calculator_ui.Add(2.0); | 246 calculator_ui.Add(2.0); |
| 236 PumpMessages(); | 247 PumpMessages(); |
| 237 EXPECT_EQ(2.0, calculator_ui.GetOutput()); | 248 EXPECT_EQ(2.0, calculator_ui.GetOutput()); |
| 238 EXPECT_FALSE(calculator_ui.encountered_error()); | 249 EXPECT_FALSE(calculator_ui.encountered_error()); |
| 239 | 250 |
| 240 calculator_ui.Multiply(5.0); | 251 calculator_ui.Multiply(5.0); |
| 241 EXPECT_FALSE(calculator_ui.encountered_error()); | 252 EXPECT_FALSE(calculator_ui.encountered_error()); |
| 242 | 253 |
| 243 // Close the server. | 254 // Close the server. |
| 244 server->internal_router()->CloseMessagePipe(); | 255 server->internal_state()->router()->CloseMessagePipe(); |
| 245 | 256 |
| 246 // The state change isn't picked up locally yet. | 257 // The state change isn't picked up locally yet. |
| 247 EXPECT_FALSE(calculator_ui.encountered_error()); | 258 EXPECT_FALSE(calculator_ui.encountered_error()); |
| 248 | 259 |
| 249 PumpMessages(); | 260 PumpMessages(); |
| 250 | 261 |
| 251 // OK, now we see the error. | 262 // OK, now we see the error. |
| 252 EXPECT_TRUE(calculator_ui.encountered_error()); | 263 EXPECT_TRUE(calculator_ui.encountered_error()); |
| 253 } | 264 } |
| 254 | 265 |
| 255 TEST_F(InterfacePtrTest, EncounteredErrorCallback) { | 266 TEST_F(InterfacePtrTest, EncounteredErrorCallback) { |
| 256 math::CalculatorPtr proxy; | 267 math::CalculatorPtr proxy; |
| 257 MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy); | 268 MathCalculatorImpl* server = BindToProxy(new MathCalculatorImpl(), &proxy); |
| 258 | 269 |
| 259 ErrorObserver error_observer; | 270 ErrorObserver error_observer; |
| 260 proxy.set_error_handler(&error_observer); | 271 proxy.set_error_handler(&error_observer); |
| 261 | 272 |
| 262 MathCalculatorUIImpl calculator_ui(proxy.Pass()); | 273 MathCalculatorUIImpl calculator_ui(proxy.Pass()); |
| 263 | 274 |
| 264 calculator_ui.Add(2.0); | 275 calculator_ui.Add(2.0); |
| 265 PumpMessages(); | 276 PumpMessages(); |
| 266 EXPECT_EQ(2.0, calculator_ui.GetOutput()); | 277 EXPECT_EQ(2.0, calculator_ui.GetOutput()); |
| 267 EXPECT_FALSE(calculator_ui.encountered_error()); | 278 EXPECT_FALSE(calculator_ui.encountered_error()); |
| 268 | 279 |
| 269 calculator_ui.Multiply(5.0); | 280 calculator_ui.Multiply(5.0); |
| 270 EXPECT_FALSE(calculator_ui.encountered_error()); | 281 EXPECT_FALSE(calculator_ui.encountered_error()); |
| 271 | 282 |
| 272 // Close the server. | 283 // Close the server. |
| 273 server->internal_router()->CloseMessagePipe(); | 284 server->internal_state()->router()->CloseMessagePipe(); |
| 274 | 285 |
| 275 // The state change isn't picked up locally yet. | 286 // The state change isn't picked up locally yet. |
| 276 EXPECT_FALSE(calculator_ui.encountered_error()); | 287 EXPECT_FALSE(calculator_ui.encountered_error()); |
| 277 | 288 |
| 278 PumpMessages(); | 289 PumpMessages(); |
| 279 | 290 |
| 280 // OK, now we see the error. | 291 // OK, now we see the error. |
| 281 EXPECT_TRUE(calculator_ui.encountered_error()); | 292 EXPECT_TRUE(calculator_ui.encountered_error()); |
| 282 | 293 |
| 283 // We should have also been able to observe the error through the | 294 // We should have also been able to observe the error through the |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 impl->BeginTest(true); | 330 impl->BeginTest(true); |
| 320 | 331 |
| 321 PumpMessages(); | 332 PumpMessages(); |
| 322 | 333 |
| 323 EXPECT_EQ(0, SelfDestructingMathCalculatorUIImpl::num_instances()); | 334 EXPECT_EQ(0, SelfDestructingMathCalculatorUIImpl::num_instances()); |
| 324 } | 335 } |
| 325 | 336 |
| 326 TEST_F(InterfacePtrTest, ReentrantWaitForIncomingMethodCall) { | 337 TEST_F(InterfacePtrTest, ReentrantWaitForIncomingMethodCall) { |
| 327 sample::ServicePtr proxy; | 338 sample::ServicePtr proxy; |
| 328 ReentrantServiceImpl* impl = BindToProxy(new ReentrantServiceImpl(), &proxy); | 339 ReentrantServiceImpl* impl = BindToProxy(new ReentrantServiceImpl(), &proxy); |
| 340 EXPECT_TRUE(impl->got_connection()); |
| 329 | 341 |
| 330 proxy->Frobinate(sample::FooPtr(), | 342 proxy->Frobinate(sample::FooPtr(), |
| 331 sample::Service::BAZ_OPTIONS_REGULAR, | 343 sample::Service::BAZ_OPTIONS_REGULAR, |
| 332 sample::PortPtr()); | 344 sample::PortPtr()); |
| 333 proxy->Frobinate(sample::FooPtr(), | 345 proxy->Frobinate(sample::FooPtr(), |
| 334 sample::Service::BAZ_OPTIONS_REGULAR, | 346 sample::Service::BAZ_OPTIONS_REGULAR, |
| 335 sample::PortPtr()); | 347 sample::PortPtr()); |
| 336 | 348 |
| 337 PumpMessages(); | 349 PumpMessages(); |
| 338 | 350 |
| 339 EXPECT_EQ(2, impl->max_call_depth()); | 351 EXPECT_EQ(2, impl->max_call_depth()); |
| 340 } | 352 } |
| 341 | 353 |
| 342 class StrongMathCalculatorImpl : public math::Calculator, public ErrorHandler { | |
| 343 public: | |
| 344 StrongMathCalculatorImpl(ScopedMessagePipeHandle handle, | |
| 345 bool* error_received, | |
| 346 bool* destroyed) | |
| 347 : error_received_(error_received), | |
| 348 destroyed_(destroyed), | |
| 349 binding_(this, handle.Pass()) { | |
| 350 binding_.set_error_handler(this); | |
| 351 } | |
| 352 ~StrongMathCalculatorImpl() override { *destroyed_ = true; } | |
| 353 | |
| 354 // math::Calculator implementation. | |
| 355 void Clear() override { binding_.client()->Output(total_); } | |
| 356 | |
| 357 void Add(double value) override { | |
| 358 total_ += value; | |
| 359 binding_.client()->Output(total_); | |
| 360 } | |
| 361 | |
| 362 void Multiply(double value) override { | |
| 363 total_ *= value; | |
| 364 binding_.client()->Output(total_); | |
| 365 } | |
| 366 | |
| 367 // ErrorHandler implementation. | |
| 368 void OnConnectionError() override { *error_received_ = true; } | |
| 369 | |
| 370 private: | |
| 371 double total_ = 0.0; | |
| 372 bool* error_received_; | |
| 373 bool* destroyed_; | |
| 374 | |
| 375 StrongBinding<math::Calculator> binding_; | |
| 376 }; | |
| 377 | |
| 378 TEST(StrongConnectorTest, Math) { | |
| 379 Environment env; | |
| 380 RunLoop loop; | |
| 381 | |
| 382 bool error_received = false; | |
| 383 bool destroyed = false; | |
| 384 MessagePipe pipe; | |
| 385 new StrongMathCalculatorImpl(pipe.handle0.Pass(), &error_received, | |
| 386 &destroyed); | |
| 387 | |
| 388 math::CalculatorPtr calc; | |
| 389 calc.Bind(pipe.handle1.Pass()); | |
| 390 | |
| 391 { | |
| 392 // Suppose this is instantiated in a process that has the other end of the | |
| 393 // message pipe. | |
| 394 MathCalculatorUIImpl calculator_ui(calc.Pass()); | |
| 395 | |
| 396 calculator_ui.Add(2.0); | |
| 397 calculator_ui.Multiply(5.0); | |
| 398 | |
| 399 loop.RunUntilIdle(); | |
| 400 | |
| 401 EXPECT_EQ(10.0, calculator_ui.GetOutput()); | |
| 402 EXPECT_FALSE(error_received); | |
| 403 EXPECT_FALSE(destroyed); | |
| 404 } | |
| 405 // Destroying calculator_ui should close the pipe and generate an error on the | |
| 406 // other | |
| 407 // end which will destroy the instance since it is strongly bound. | |
| 408 | |
| 409 loop.RunUntilIdle(); | |
| 410 EXPECT_TRUE(error_received); | |
| 411 EXPECT_TRUE(destroyed); | |
| 412 } | |
| 413 | |
| 414 class WeakMathCalculatorImpl : public math::Calculator, public ErrorHandler { | |
| 415 public: | |
| 416 WeakMathCalculatorImpl(ScopedMessagePipeHandle handle, | |
| 417 bool* error_received, | |
| 418 bool* destroyed) | |
| 419 : error_received_(error_received), | |
| 420 destroyed_(destroyed), | |
| 421 binding_(this, handle.Pass()) { | |
| 422 binding_.set_error_handler(this); | |
| 423 } | |
| 424 ~WeakMathCalculatorImpl() override { *destroyed_ = true; } | |
| 425 | |
| 426 void Clear() override { binding_.client()->Output(total_); } | |
| 427 | |
| 428 void Add(double value) override { | |
| 429 total_ += value; | |
| 430 binding_.client()->Output(total_); | |
| 431 } | |
| 432 | |
| 433 void Multiply(double value) override { | |
| 434 total_ *= value; | |
| 435 binding_.client()->Output(total_); | |
| 436 } | |
| 437 | |
| 438 // ErrorHandler implementation. | |
| 439 void OnConnectionError() override { *error_received_ = true; } | |
| 440 | |
| 441 private: | |
| 442 double total_ = 0.0; | |
| 443 bool* error_received_; | |
| 444 bool* destroyed_; | |
| 445 | |
| 446 Binding<math::Calculator> binding_; | |
| 447 }; | |
| 448 | |
| 449 TEST(WeakConnectorTest, Math) { | |
| 450 Environment env; | |
| 451 RunLoop loop; | |
| 452 | |
| 453 bool error_received = false; | |
| 454 bool destroyed = false; | |
| 455 MessagePipe pipe; | |
| 456 WeakMathCalculatorImpl impl(pipe.handle0.Pass(), &error_received, &destroyed); | |
| 457 | |
| 458 math::CalculatorPtr calc; | |
| 459 calc.Bind(pipe.handle1.Pass()); | |
| 460 | |
| 461 { | |
| 462 // Suppose this is instantiated in a process that has the other end of the | |
| 463 // message pipe. | |
| 464 MathCalculatorUIImpl calculator_ui(calc.Pass()); | |
| 465 | |
| 466 calculator_ui.Add(2.0); | |
| 467 calculator_ui.Multiply(5.0); | |
| 468 | |
| 469 loop.RunUntilIdle(); | |
| 470 | |
| 471 EXPECT_EQ(10.0, calculator_ui.GetOutput()); | |
| 472 EXPECT_FALSE(error_received); | |
| 473 EXPECT_FALSE(destroyed); | |
| 474 // Destroying calculator_ui should close the pipe and generate an error on | |
| 475 // the other | |
| 476 // end which will destroy the instance since it is strongly bound. | |
| 477 } | |
| 478 | |
| 479 loop.RunUntilIdle(); | |
| 480 EXPECT_TRUE(error_received); | |
| 481 EXPECT_FALSE(destroyed); | |
| 482 } | |
| 483 | |
| 484 } // namespace | 354 } // namespace |
| 485 } // namespace test | 355 } // namespace test |
| 486 } // namespace mojo | 356 } // namespace mojo |
| OLD | NEW |