| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromecast/mojo/binder_factory.h" |
| |
| #include <string> |
| |
| #include "base/functional/bind.h" |
| #include "base/test/task_environment.h" |
| #include "chromecast/mojo/test/test_interfaces.test-mojom.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::_; |
| |
| namespace chromecast { |
| |
| class MockInterface : public test::mojom::StringInterface, |
| public test::mojom::IntInterface, |
| public test::mojom::BoolInterface { |
| public: |
| MOCK_METHOD(void, StringMethod, (const std::string& s), (override)); |
| MOCK_METHOD(void, IntMethod, (int32_t i), (override)); |
| MOCK_METHOD(void, BoolMethod, (bool b), (override)); |
| }; |
| |
| class MockErrorHandler { |
| public: |
| MOCK_METHOD(void, OnError, ()); |
| }; |
| |
| class BinderFactoryTest : public testing::Test { |
| protected: |
| BinderFactoryTest() {} |
| |
| base::test::TaskEnvironment task_environment_; |
| |
| MockInterface mock_interface_; |
| }; |
| |
| TEST_F(BinderFactoryTest, BinderFactoryBind) { |
| BinderFactory<test::mojom::StringInterface> s_factory(&mock_interface_); |
| |
| mojo::Remote<test::mojom::StringInterface> s_remote; |
| s_factory.Bind(s_remote.BindNewPipeAndPassReceiver()); |
| |
| // Verify implementation is connected. |
| std::string s = "Hello, world!"; |
| EXPECT_CALL(mock_interface_, StringMethod(s)); |
| s_remote->StringMethod(s); |
| task_environment_.RunUntilIdle(); |
| } |
| |
| TEST_F(BinderFactoryTest, BinderFactoryGetBinder) { |
| BinderFactory<test::mojom::StringInterface> s_factory(&mock_interface_); |
| |
| auto binder = s_factory.GetBinder(); |
| ASSERT_TRUE(!binder.is_null()); |
| |
| mojo::Remote<test::mojom::StringInterface> s_remote; |
| s_factory.Bind(s_remote.BindNewPipeAndPassReceiver()); |
| |
| // Verify implementation is connected. |
| std::string s = "Hello, world!"; |
| EXPECT_CALL(mock_interface_, StringMethod(s)); |
| s_remote->StringMethod(s); |
| task_environment_.RunUntilIdle(); |
| } |
| |
| TEST_F(BinderFactoryTest, BinderFactoryLifetime) { |
| MockErrorHandler s_handler; |
| auto s_factory = |
| std::make_unique<BinderFactory<test::mojom::StringInterface>>( |
| &mock_interface_); |
| |
| auto binder = s_factory->GetBinder(); |
| ASSERT_TRUE(!binder.is_null()); |
| |
| mojo::Remote<test::mojom::StringInterface> s_remote; |
| s_factory->Bind(s_remote.BindNewPipeAndPassReceiver()); |
| |
| s_remote.set_disconnect_handler( |
| base::BindOnce(&MockErrorHandler::OnError, base::Unretained(&s_handler))); |
| |
| // Remotes which were bound via the BinderFactory will invalidated when the |
| // factory is destroyed. |
| EXPECT_CALL(s_handler, OnError()).Times(1); |
| |
| s_factory.reset(); |
| task_environment_.RunUntilIdle(); |
| } |
| |
| TEST_F(BinderFactoryTest, MultiBinderFactory) { |
| MockErrorHandler s_handler; |
| MockErrorHandler i_handler; |
| auto factory = std::make_unique<MultiBinderFactory>(); |
| factory->AddInterface<test::mojom::StringInterface>(&mock_interface_); |
| factory->AddInterface<test::mojom::IntInterface>(&mock_interface_); |
| |
| auto s_binder = factory->GetBinder<test::mojom::StringInterface>(); |
| ASSERT_FALSE(s_binder.is_null()); |
| auto i_binder = factory->GetBinder<test::mojom::IntInterface>(); |
| ASSERT_FALSE(i_binder.is_null()); |
| |
| // There is no binder for BoolInterface. |
| ASSERT_TRUE(factory->GetBinder<test::mojom::BoolInterface>().is_null()); |
| |
| mojo::Remote<test::mojom::StringInterface> s_remote; |
| s_binder.Run(s_remote.BindNewPipeAndPassReceiver()); |
| |
| mojo::Remote<test::mojom::IntInterface> i_remote; |
| i_binder.Run(i_remote.BindNewPipeAndPassReceiver()); |
| |
| std::string s = "Hello, world!"; |
| EXPECT_CALL(mock_interface_, StringMethod(s)); |
| s_remote->StringMethod(s); |
| task_environment_.RunUntilIdle(); |
| |
| int i = 1234; |
| EXPECT_CALL(mock_interface_, IntMethod(i)); |
| i_remote->IntMethod(i); |
| task_environment_.RunUntilIdle(); |
| |
| s_remote.set_disconnect_handler( |
| base::BindOnce(&MockErrorHandler::OnError, base::Unretained(&s_handler))); |
| i_remote.set_disconnect_handler( |
| base::BindOnce(&MockErrorHandler::OnError, base::Unretained(&i_handler))); |
| |
| // Pointers which were bound via the MultiBinderFactory will invalidated when |
| // the factory is destroyed. |
| EXPECT_CALL(s_handler, OnError()).Times(1); |
| EXPECT_CALL(i_handler, OnError()).Times(1); |
| |
| factory.reset(); |
| task_environment_.RunUntilIdle(); |
| } |
| |
| } // namespace chromecast |