Index: mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc |
diff --git a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc |
index 431a84425076dbd97dfb612a3501ee41b937e11e..39a63581daec5346f86b248c7ef17725e1d06842 100644 |
--- a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc |
+++ b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc |
@@ -19,6 +19,7 @@ |
#include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h" |
#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
#include "mojo/public/interfaces/bindings/tests/scoping.mojom.h" |
+#include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace mojo { |
@@ -932,6 +933,80 @@ TEST_F(InterfacePtrTest, ThreadSafeInterfacePointerWithTaskRunner) { |
thread_safe_ptr = nullptr; |
} |
+class TestSyncImpl : public TestSync { |
+ public: |
+ explicit TestSyncImpl(TestSyncRequest request) |
+ : binding_(this, std::move(request)) {} |
+ |
+ // TestSync implementation: |
+ void Ping(const PingCallback& callback) override { callback.Run(); } |
+ void Echo(int32_t value, const EchoCallback& callback) override { |
+ callback.Run(value); |
+ } |
+ void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { |
+ callback.Run(value); |
+ } |
+ |
+ Binding<TestSync>* binding() { return &binding_; } |
+ |
+ private: |
+ Binding<TestSync> binding_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestSyncImpl); |
+}; |
+ |
+TEST_F(InterfacePtrTest, ThreadSafeSyncCall) { |
+ // Create and start the thread from where we'll bind the interface pointer. |
+ base::Thread other_thread("service test thread"); |
+ other_thread.Start(); |
+ const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner = |
+ other_thread.message_loop()->task_runner(); |
+ |
+ TestSyncPtr ptr; |
+ TestSyncRequest request(&ptr); |
+ |
+ // Create a ThreadSafeInterfacePtr that we'll bind from a different thread. |
+ scoped_refptr<ThreadSafeTestSyncPtr> thread_safe_ptr = |
+ ThreadSafeTestSyncPtr::Create(ptr.PassInterface(), |
+ other_thread_task_runner); |
+ ASSERT_TRUE(thread_safe_ptr); |
+ |
+ TestSyncImpl* test_sync_impl = nullptr; |
+ { |
+ base::RunLoop run_loop; |
+ auto create_impl = base::Bind( |
+ [](TestSyncRequest request, TestSyncImpl** test_sync_impl) { |
+ // In real life, the implementation would have a legitimate owner. |
+ *test_sync_impl = new TestSyncImpl(std::move(request)); |
+ }, |
+ base::Passed(&request), &test_sync_impl); |
+ other_thread_task_runner->PostTaskAndReply(FROM_HERE, create_impl, |
+ run_loop.QuitClosure()); |
+ run_loop.Run(); |
+ } |
+ |
+ int32_t output = -1; |
+ (*thread_safe_ptr)->Echo(123, &output); |
+ ASSERT_EQ(123, output); |
+ |
+ other_thread_task_runner->DeleteSoon(FROM_HERE, test_sync_impl); |
+ |
+ // Reset the pointer now so the InterfacePtr associated resources can be |
+ // deleted before the background thread's message loop is invalidated. |
+ thread_safe_ptr = nullptr; |
+} |
+ |
+TEST_F(InterfacePtrTest, ThreadSafeSyncCallSameThread) { |
+ TestSyncPtr ptr; |
+ auto impl = base::MakeUnique<TestSyncImpl>(MakeRequest(&ptr)); |
+ scoped_refptr<ThreadSafeTestSyncPtr> thread_safe_ptr = |
+ ThreadSafeTestSyncPtr::Create(std::move(ptr)); |
+ |
+ int32_t output = -1; |
+ (*thread_safe_ptr)->Echo(123, &output); |
+ ASSERT_EQ(123, output); |
+} |
+ |
} // namespace |
} // namespace test |
} // namespace mojo |