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 d0e5f108880aa2bfe3a7e8018a59a496e8be3022..084e080ad36512aca17a1c1ff37c01ac64d4a39e 100644 |
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc |
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc |
@@ -202,6 +202,60 @@ struct ImplTraits<TestSyncMaster> { |
}; |
template <typename Interface> |
+using ImplTypeFor = typename ImplTraits<Interface>::Type; |
+ |
+// A wrapper for either an InterfacePtr or scoped_refptr<ThreadSafeInterfacePtr> |
+// that exposes the InterfacePtr interface. |
+template <typename Interface> |
+class PtrWrapper { |
+ public: |
+ explicit PtrWrapper(InterfacePtr<Interface> ptr) : ptr_(std::move(ptr)) {} |
+ |
+ explicit PtrWrapper( |
+ scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr) |
+ : thread_safe_ptr_(thread_safe_ptr) {} |
+ |
+ PtrWrapper(PtrWrapper&& other) = default; |
+ |
+ Interface* operator->() { |
+ return thread_safe_ptr_ ? thread_safe_ptr_->get() : ptr_.get(); |
+ } |
+ |
+ void set_connection_error_handler(const base::Closure& error_handler) { |
+ DCHECK(!thread_safe_ptr_); |
+ ptr_.set_connection_error_handler(error_handler); |
+ } |
+ |
+ void reset() { |
+ ptr_ = nullptr; |
+ thread_safe_ptr_ = nullptr; |
+ } |
+ |
+ private: |
+ InterfacePtr<Interface> ptr_; |
+ scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PtrWrapper); |
+}; |
+ |
+// The type parameter for SyncMethodCommonTests for varying the Interface and |
+// whether to use InterfacePtr or ThreadSafeInterfacePtr. |
+template <typename InterfaceT, bool use_thread_safe_ptr> |
+struct TestParams { |
+ using Interface = InterfaceT; |
+ static const bool kIsThreadSafeInterfacePtrTest = use_thread_safe_ptr; |
+ |
+ static PtrWrapper<InterfaceT> Wrap(InterfacePtr<Interface> ptr) { |
+ if (kIsThreadSafeInterfacePtrTest) { |
+ return PtrWrapper<Interface>( |
+ ThreadSafeInterfacePtr<Interface>::Create(std::move(ptr))); |
+ } else { |
+ return PtrWrapper<Interface>(std::move(ptr)); |
+ } |
+ } |
+}; |
+ |
+template <typename Interface> |
class TestSyncServiceThread { |
public: |
TestSyncServiceThread() |
@@ -211,7 +265,7 @@ class TestSyncServiceThread { |
void SetUp(InterfaceRequest<Interface> request) { |
CHECK(thread_.task_runner()->BelongsToCurrentThread()); |
- impl_.reset(new typename ImplTraits<Interface>::Type(std::move(request))); |
+ impl_.reset(new ImplTypeFor<Interface>(std::move(request))); |
impl_->set_ping_handler( |
[this](const typename Interface::PingCallback& callback) { |
{ |
@@ -236,7 +290,7 @@ class TestSyncServiceThread { |
private: |
base::Thread thread_; |
- std::unique_ptr<typename ImplTraits<Interface>::Type> impl_; |
+ std::unique_ptr<ImplTypeFor<Interface>> impl_; |
mutable base::Lock lock_; |
bool ping_called_; |
@@ -334,12 +388,20 @@ TestSync::AsyncEchoCallback BindAsyncEchoCallback(Func func) { |
// TestSync (without associated interfaces) and TestSyncMaster (with associated |
// interfaces) exercise MultiplexRouter with different configurations. |
-using InterfaceTypes = testing::Types<TestSync, TestSyncMaster>; |
+// Each test is run once with an InterfacePtr and once with a |
+// ThreadSafeInterfacePtr to ensure that they behave the same with respect to |
+// sync calls. |
+using InterfaceTypes = testing::Types<TestParams<TestSync, true>, |
+ TestParams<TestSync, false>, |
+ TestParams<TestSyncMaster, true>, |
+ TestParams<TestSyncMaster, false>>; |
TYPED_TEST_CASE(SyncMethodCommonTest, InterfaceTypes); |
TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) { |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
base::RunLoop run_loop; |
ptr->Echo(123, base::Bind(&ExpectValueAndRunClosure, 123, |
@@ -348,13 +410,16 @@ TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) { |
} |
TYPED_TEST(SyncMethodCommonTest, BasicSyncCalls) { |
- InterfacePtr<TypeParam> ptr; |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ InterfaceRequest<Interface> request = MakeRequest(&interface_ptr); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
- TestSyncServiceThread<TypeParam> service_thread; |
+ TestSyncServiceThread<Interface> service_thread; |
service_thread.thread()->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&TestSyncServiceThread<TypeParam>::SetUp, |
- base::Unretained(&service_thread), |
- base::Passed(MakeRequest(&ptr)))); |
+ FROM_HERE, |
+ base::Bind(&TestSyncServiceThread<Interface>::SetUp, |
+ base::Unretained(&service_thread), base::Passed(&request))); |
ASSERT_TRUE(ptr->Ping()); |
ASSERT_TRUE(service_thread.ping_called()); |
@@ -364,8 +429,9 @@ TYPED_TEST(SyncMethodCommonTest, BasicSyncCalls) { |
base::RunLoop run_loop; |
service_thread.thread()->task_runner()->PostTaskAndReply( |
- FROM_HERE, base::Bind(&TestSyncServiceThread<TypeParam>::TearDown, |
- base::Unretained(&service_thread)), |
+ FROM_HERE, |
+ base::Bind(&TestSyncServiceThread<Interface>::TearDown, |
+ base::Unretained(&service_thread)), |
run_loop.QuitClosure()); |
run_loop.Run(); |
} |
@@ -374,9 +440,11 @@ TYPED_TEST(SyncMethodCommonTest, ReenteredBySyncMethodBinding) { |
// Test that an interface pointer waiting for a sync call response can be |
// reentered by a binding serving sync methods on the same thread. |
- InterfacePtr<TypeParam> ptr; |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
// The binding lives on the same thread as the interface pointer. |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
int32_t output_value = -1; |
ASSERT_TRUE(ptr->Echo(42, &output_value)); |
EXPECT_EQ(42, output_value); |
@@ -386,8 +454,10 @@ TYPED_TEST(SyncMethodCommonTest, InterfacePtrDestroyedDuringSyncCall) { |
// Test that it won't result in crash or hang if an interface pointer is |
// destroyed while it is waiting for a sync call response. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
impl.set_ping_handler([&ptr](const TestSync::PingCallback& callback) { |
ptr.reset(); |
callback.Run(); |
@@ -400,8 +470,10 @@ TYPED_TEST(SyncMethodCommonTest, BindingDestroyedDuringSyncCall) { |
// closed (and therefore the message pipe handle is closed) while the |
// corresponding interface pointer is waiting for a sync call response. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
impl.set_ping_handler([&impl](const TestSync::PingCallback& callback) { |
impl.binding()->Close(); |
callback.Run(); |
@@ -413,8 +485,10 @@ TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithInOrderResponses) { |
// Test that we can call a sync method on an interface ptr, while there is |
// already a sync call ongoing. The responses arrive in order. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
// The same variable is used to store the output of the two sync calls, in |
// order to test that responses are handled in the correct order. |
@@ -439,8 +513,10 @@ TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithOutOfOrderResponses) { |
// Test that we can call a sync method on an interface ptr, while there is |
// already a sync call ongoing. The responses arrive out of order. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
// The same variable is used to store the output of the two sync calls, in |
// order to test that responses are handled in the correct order. |
@@ -465,8 +541,10 @@ TYPED_TEST(SyncMethodCommonTest, AsyncResponseQueuedDuringSyncCall) { |
// Test that while an interface pointer is waiting for the response to a sync |
// call, async responses are queued until the sync call completes. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
int32_t async_echo_request_value = -1; |
TestSync::AsyncEchoCallback async_echo_request_callback; |
@@ -521,8 +599,10 @@ TYPED_TEST(SyncMethodCommonTest, AsyncRequestQueuedDuringSyncCall) { |
// call, async requests for a binding running on the same thread are queued |
// until the sync call completes. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> interface_ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
bool async_echo_request_dispatched = false; |
impl.set_async_echo_handler([&async_echo_request_dispatched]( |
@@ -572,8 +652,14 @@ TYPED_TEST(SyncMethodCommonTest, |
// before the queued messages are processed, the connection error |
// notification is delayed until all the queued messages are processed. |
- InterfacePtr<TypeParam> ptr; |
- typename ImplTraits<TypeParam>::Type impl(MakeRequest(&ptr)); |
+ // ThreadSafeInterfacePtr doesn't guarantee that messages are delivered before |
+ // error notifications, so skip it for this test. |
+ if (TypeParam::kIsThreadSafeInterfacePtrTest) |
+ return; |
+ |
+ using Interface = typename TypeParam::Interface; |
+ InterfacePtr<Interface> ptr; |
+ ImplTypeFor<Interface> impl(MakeRequest(&ptr)); |
int32_t async_echo_request_value = -1; |
TestSync::AsyncEchoCallback async_echo_request_callback; |
@@ -648,14 +734,15 @@ TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) { |
// the sync call to return false, and run the connection error handler |
// asynchronously. |
+ using Interface = typename TypeParam::Interface; |
MessagePipe pipe; |
- InterfacePtr<TypeParam> ptr; |
- ptr.Bind(InterfacePtrInfo<TypeParam>(std::move(pipe.handle0), 0u)); |
+ InterfacePtr<Interface> interface_ptr; |
+ interface_ptr.Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u)); |
+ auto ptr = TypeParam::Wrap(std::move(interface_ptr)); |
MessagePipeHandle raw_binding_handle = pipe.handle1.get(); |
- typename ImplTraits<TypeParam>::Type impl( |
- MakeRequest<TypeParam>(std::move(pipe.handle1))); |
+ ImplTypeFor<Interface> impl(MakeRequest<Interface>(std::move(pipe.handle1))); |
impl.set_echo_handler([&raw_binding_handle]( |
int32_t value, const TestSync::EchoCallback& callback) { |
@@ -670,17 +757,22 @@ TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) { |
bool connection_error_dispatched = false; |
base::RunLoop run_loop; |
- ptr.set_connection_error_handler( |
- base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched, |
- run_loop.QuitClosure())); |
+ // ThreadSafeInterfacePtr doesn't support setting connection error handlers. |
+ if (!TypeParam::kIsThreadSafeInterfacePtrTest) { |
+ ptr.set_connection_error_handler(base::Bind(&SetFlagAndRunClosure, |
+ &connection_error_dispatched, |
+ run_loop.QuitClosure())); |
+ } |
int32_t result_value = -1; |
ASSERT_FALSE(ptr->Echo(456, &result_value)); |
EXPECT_EQ(-1, result_value); |
ASSERT_FALSE(connection_error_dispatched); |
- run_loop.Run(); |
- ASSERT_TRUE(connection_error_dispatched); |
+ if (!TypeParam::kIsThreadSafeInterfacePtrTest) { |
+ run_loop.Run(); |
+ ASSERT_TRUE(connection_error_dispatched); |
+ } |
} |
TEST_F(SyncMethodAssociatedTest, ReenteredBySyncMethodAssoBindingOfSameRouter) { |