| 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 |