Index: third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_unittest.cc |
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2e38f1314924005daae6c40be2dc50a892a68868 |
--- /dev/null |
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/binding_unittest.cc |
@@ -0,0 +1,116 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "mojo/public/cpp/bindings/binding.h" |
+#include "mojo/public/cpp/environment/environment.h" |
+#include "mojo/public/cpp/utility/run_loop.h" |
+#include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace mojo { |
+namespace { |
+ |
+class ServiceImpl : public sample::Service { |
+ public: |
+ ServiceImpl() {} |
+ ~ServiceImpl() override {} |
+ |
+ private: |
+ // sample::Service implementation |
+ void Frobinate(sample::FooPtr foo, |
+ BazOptions options, |
+ sample::PortPtr port, |
+ const FrobinateCallback& callback) override { |
+ callback.Run(1); |
+ } |
+ void GetPort(InterfaceRequest<sample::Port> port) override {} |
+}; |
+ |
+class RecordingErrorHandler : public ErrorHandler { |
+ public: |
+ RecordingErrorHandler() : error_(false) {} |
+ ~RecordingErrorHandler() override {} |
+ |
+ bool encountered_error() const { return error_; } |
+ |
+ private: |
+ // ErrorHandler implementation. |
+ void OnConnectionError() override { error_ = true; } |
+ |
+ bool error_; |
+}; |
+ |
+class BindingTest : public testing::Test { |
+ public: |
+ BindingTest() {} |
+ ~BindingTest() override {} |
+ |
+ protected: |
+ RecordingErrorHandler handler_; |
+ ServiceImpl impl_; |
+ Environment env_; |
+ RunLoop loop_; |
+}; |
+ |
+// Tests that destroying a mojo::Binding closes the bound message pipe handle. |
+TEST_F(BindingTest, DestroyClosesMessagePipe) { |
+ sample::ServicePtr ptr; |
+ auto request = GetProxy(&ptr); |
+ ptr.set_error_handler(&handler_); |
+ bool called = false; |
+ auto called_cb = [&called](int32_t result) { called = true; }; |
+ { |
+ Binding<sample::Service> binding(&impl_, request.Pass()); |
+ ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
+ called_cb); |
+ loop_.RunUntilIdle(); |
+ EXPECT_TRUE(called); |
+ EXPECT_FALSE(handler_.encountered_error()); |
+ } |
+ // Now that the Binding is out of scope we should detect an error on the other |
+ // end of the pipe. |
+ loop_.RunUntilIdle(); |
+ EXPECT_TRUE(handler_.encountered_error()); |
+ |
+ // And calls should fail. |
+ called = false; |
+ ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
+ called_cb); |
+ loop_.RunUntilIdle(); |
+ EXPECT_FALSE(called); |
+} |
+ |
+// Tests that explicitly calling Unbind followed by rebinding works. |
+TEST_F(BindingTest, Unbind) { |
+ sample::ServicePtr ptr; |
+ Binding<sample::Service> binding(&impl_, GetProxy(&ptr)); |
+ |
+ bool called = false; |
+ auto called_cb = [&called](int32_t result) { called = true; }; |
+ ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
+ called_cb); |
+ loop_.RunUntilIdle(); |
+ EXPECT_TRUE(called); |
+ |
+ called = false; |
+ auto request = binding.Unbind(); |
+ EXPECT_FALSE(binding.is_bound()); |
+ // All calls should fail when not bound... |
+ ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
+ called_cb); |
+ loop_.RunUntilIdle(); |
+ EXPECT_FALSE(called); |
+ |
+ called = false; |
+ binding.Bind(request.Pass()); |
+ EXPECT_TRUE(binding.is_bound()); |
+ // ...and should succeed again when the rebound. |
+ ptr->Frobinate(nullptr, sample::Service::BAZ_OPTIONS_REGULAR, nullptr, |
+ called_cb); |
+ loop_.RunUntilIdle(); |
+ EXPECT_TRUE(called); |
+} |
+ |
+} // namespace |
+} // mojo |