Index: mojo/public/cpp/bindings/tests/sync_method_unittest.cc |
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc |
index 3d212051b82b3edaa7dd3c10e573ad32056ff45e..c990b5c48910ed3fbdc44783fe25e023d7767376 100644 |
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc |
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc |
@@ -9,6 +9,7 @@ |
#include "base/run_loop.h" |
#include "base/threading/thread.h" |
#include "mojo/message_pump/message_pump_mojo.h" |
+#include "mojo/public/cpp/bindings/associated_binding.h" |
#include "mojo/public/cpp/bindings/binding.h" |
#include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -33,6 +34,16 @@ class TestSyncCommonImpl { |
async_echo_handler_ = handler; |
} |
+ using SendInterfaceHandler = Callback<void(TestSyncAssociatedPtrInfo)>; |
+ void set_send_interface_handler(const SendInterfaceHandler& handler) { |
+ send_interface_handler_ = handler; |
+ } |
+ |
+ using SendRequestHandler = Callback<void(TestSyncAssociatedRequest)>; |
+ void set_send_request_handler(const SendRequestHandler& handler) { |
+ send_request_handler_ = handler; |
+ } |
+ |
void PingImpl(const Callback<void()>& callback) { |
if (ping_handler_.is_null()) { |
callback.Run(); |
@@ -54,11 +65,19 @@ class TestSyncCommonImpl { |
} |
async_echo_handler_.Run(value, callback); |
} |
+ void SendInterfaceImpl(TestSyncAssociatedPtrInfo ptr) { |
+ send_interface_handler_.Run(std::move(ptr)); |
+ } |
+ void SendRequestImpl(TestSyncAssociatedRequest request) { |
+ send_request_handler_.Run(std::move(request)); |
+ } |
private: |
PingHandler ping_handler_; |
EchoHandler echo_handler_; |
AsyncEchoHandler async_echo_handler_; |
+ SendInterfaceHandler send_interface_handler_; |
+ SendRequestHandler send_request_handler_; |
DISALLOW_COPY_AND_ASSIGN(TestSyncCommonImpl); |
}; |
@@ -85,6 +104,56 @@ class TestSyncImpl : public TestSync, public TestSyncCommonImpl { |
DISALLOW_COPY_AND_ASSIGN(TestSyncImpl); |
}; |
+class TestSyncMasterImpl : public TestSyncMaster, public TestSyncCommonImpl { |
+ public: |
+ explicit TestSyncMasterImpl(TestSyncMasterRequest request) |
+ : binding_(this, std::move(request)) {} |
+ |
+ // TestSyncMaster implementation: |
+ void Ping(const PingCallback& callback) override { PingImpl(callback); } |
+ void Echo(int32_t value, const EchoCallback& callback) override { |
+ EchoImpl(value, callback); |
+ } |
+ void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { |
+ AsyncEchoImpl(value, callback); |
+ } |
+ void SendInterface(TestSyncAssociatedPtrInfo ptr) override { |
+ SendInterfaceImpl(std::move(ptr)); |
+ } |
+ void SendRequest(TestSyncAssociatedRequest request) override { |
+ SendRequestImpl(std::move(request)); |
+ } |
+ |
+ Binding<TestSyncMaster>* binding() { return &binding_; } |
+ |
+ private: |
+ Binding<TestSyncMaster> binding_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestSyncMasterImpl); |
+}; |
+ |
+class TestSyncAssoImpl : public TestSync, public TestSyncCommonImpl { |
Ken Rockot(use gerrit already)
2016/03/29 06:36:50
nit: This name is a bit weird. Could it just be Te
yzshen1
2016/03/29 16:19:01
Done.
|
+ public: |
+ explicit TestSyncAssoImpl(TestSyncAssociatedRequest request) |
+ : binding_(this, std::move(request)) {} |
+ |
+ // TestSync implementation: |
+ void Ping(const PingCallback& callback) override { PingImpl(callback); } |
+ void Echo(int32_t value, const EchoCallback& callback) override { |
+ EchoImpl(value, callback); |
+ } |
+ void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { |
+ AsyncEchoImpl(value, callback); |
+ } |
+ |
+ AssociatedBinding<TestSync>* binding() { return &binding_; } |
+ |
+ private: |
+ AssociatedBinding<TestSync> binding_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestSyncAssoImpl); |
+}; |
+ |
template <typename Interface> |
struct ImplTraits; |
@@ -93,6 +162,11 @@ struct ImplTraits<TestSync> { |
using Type = TestSyncImpl; |
}; |
+template <> |
+struct ImplTraits<TestSyncMaster> { |
+ using Type = TestSyncMasterImpl; |
+}; |
+ |
template <typename Interface> |
class TestSyncServiceThread { |
public: |
@@ -139,17 +213,78 @@ class TestSyncServiceThread { |
DISALLOW_COPY_AND_ASSIGN(TestSyncServiceThread); |
}; |
-template <typename T> |
-class SyncMethodCommonTest : public testing::Test { |
+class SyncMethodTest : public testing::Test { |
public: |
- SyncMethodCommonTest() : loop_(common::MessagePumpMojo::Create()) {} |
- ~SyncMethodCommonTest() override { loop_.RunUntilIdle(); } |
+ SyncMethodTest() : loop_(common::MessagePumpMojo::Create()) {} |
+ ~SyncMethodTest() override { loop_.RunUntilIdle(); } |
- private: |
+ protected: |
base::MessageLoop loop_; |
}; |
-using InterfaceTypes = testing::Types<TestSync>; |
+template <typename T> |
+class SyncMethodCommonTest : public SyncMethodTest { |
+ public: |
+ SyncMethodCommonTest() {} |
+ ~SyncMethodCommonTest() override {} |
+}; |
+ |
+class SyncMethodAssociatedTest : public SyncMethodTest { |
+ public: |
+ SyncMethodAssociatedTest() {} |
+ ~SyncMethodAssociatedTest() override {} |
+ |
+ protected: |
+ void SetUp() override { |
+ master_impl_.reset(new TestSyncMasterImpl(GetProxy(&master_ptr_))); |
+ |
+ master_ptr_.associated_group()->CreateAssociatedInterface( |
+ AssociatedGroup::WILL_PASS_REQUEST, &asso_ptr_info_, &asso_request_); |
+ master_ptr_.associated_group()->CreateAssociatedInterface( |
+ AssociatedGroup::WILL_PASS_PTR, &opposite_asso_ptr_info_, |
+ &opposite_asso_request_); |
+ |
+ master_impl_->set_send_interface_handler( |
+ [this](TestSyncAssociatedPtrInfo ptr) { |
+ opposite_asso_ptr_info_ = std::move(ptr); |
+ }); |
+ base::RunLoop run_loop; |
+ master_impl_->set_send_request_handler( |
+ [this, &run_loop](TestSyncAssociatedRequest request) { |
+ asso_request_ = std::move(request); |
+ run_loop.Quit(); |
+ }); |
+ |
+ master_ptr_->SendInterface(std::move(opposite_asso_ptr_info_)); |
+ master_ptr_->SendRequest(std::move(asso_request_)); |
+ run_loop.Run(); |
+ } |
+ |
+ void TearDown() override { |
+ asso_ptr_info_ = TestSyncAssociatedPtrInfo(); |
+ asso_request_ = TestSyncAssociatedRequest(); |
+ opposite_asso_ptr_info_ = TestSyncAssociatedPtrInfo(); |
+ opposite_asso_request_ = TestSyncAssociatedRequest(); |
+ |
+ master_ptr_ = nullptr; |
+ master_impl_.reset(); |
+ } |
+ |
+ InterfacePtr<TestSyncMaster> master_ptr_; |
+ scoped_ptr<TestSyncMasterImpl> master_impl_; |
+ |
+ // An associated interface whose binding lives at the |master_impl_| side. |
+ TestSyncAssociatedPtrInfo asso_ptr_info_; |
+ TestSyncAssociatedRequest asso_request_; |
+ |
+ // An associated interface whose binding lives at the |master_ptr_| side. |
+ TestSyncAssociatedPtrInfo opposite_asso_ptr_info_; |
+ TestSyncAssociatedRequest opposite_asso_request_; |
+}; |
+ |
+// TestSync and TestSyncMaster exercise Router and MultiplexRouter, |
+// respectively. |
+using InterfaceTypes = testing::Types<TestSync, TestSyncMaster>; |
TYPED_TEST_CASE(SyncMethodCommonTest, InterfaceTypes); |
TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) { |
@@ -497,6 +632,57 @@ TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) { |
ASSERT_TRUE(connection_error_dispatched); |
} |
+TEST_F(SyncMethodAssociatedTest, ReenteredBySyncMethodAssoBindingOfSameRouter) { |
+ // Test that an interface pointer waiting for a sync call response can be |
+ // reentered by an associated binding serving sync methods on the same thread. |
+ // The associated binding belongs to the same MultiplexRouter as the waiting |
+ // interface pointer. |
+ |
+ TestSyncAssoImpl opposite_asso_impl(std::move(opposite_asso_request_)); |
+ TestSyncAssociatedPtr opposite_asso_ptr; |
+ opposite_asso_ptr.Bind(std::move(opposite_asso_ptr_info_)); |
+ |
+ master_impl_->set_echo_handler([&opposite_asso_ptr]( |
+ int32_t value, const TestSyncMaster::EchoCallback& callback) { |
+ int32_t result_value = -1; |
+ |
+ ASSERT_TRUE(opposite_asso_ptr->Echo(123, &result_value)); |
+ EXPECT_EQ(123, result_value); |
+ callback.Run(value); |
+ }); |
+ |
+ int32_t result_value = -1; |
+ ASSERT_TRUE(master_ptr_->Echo(456, &result_value)); |
+ EXPECT_EQ(456, result_value); |
+} |
+ |
+TEST_F(SyncMethodAssociatedTest, |
+ ReenteredBySyncMethodAssoBindingOfDifferentRouter) { |
+ // Test that an interface pointer waiting for a sync call response can be |
+ // reentered by an associated binding serving sync methods on the same thread. |
+ // The associated binding belongs to a different MultiplexRouter as the |
+ // waiting interface pointer. |
+ |
+ TestSyncAssoImpl asso_impl(std::move(asso_request_)); |
+ TestSyncAssociatedPtr asso_ptr; |
+ asso_ptr.Bind(std::move(asso_ptr_info_)); |
+ |
+ master_impl_->set_echo_handler( |
+ [&asso_ptr](int32_t value, const TestSyncMaster::EchoCallback& callback) { |
+ int32_t result_value = -1; |
+ |
+ ASSERT_TRUE(asso_ptr->Echo(123, &result_value)); |
+ EXPECT_EQ(123, result_value); |
+ callback.Run(value); |
+ }); |
+ |
+ int32_t result_value = -1; |
+ ASSERT_TRUE(master_ptr_->Echo(456, &result_value)); |
+ EXPECT_EQ(456, result_value); |
+} |
+ |
+// TODO(yzshen): Add more tests related to associated interfaces. |
+ |
} // namespace |
} // namespace test |
} // namespace mojo |