#include "chromecast/mojo/interface_bundle.h"
#include <string>
#include "base/functional/bind.h"
#include "base/test/task_environment.h"
#include "chromecast/mojo/remote_interfaces.h"
#include "chromecast/mojo/test/test_interfaces.test-mojom.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 InterfaceBundleTest : public testing::Test {
protected:
InterfaceBundleTest() {}
base::test::TaskEnvironment task_environment_;
MockInterface mock_interface_;
};
TEST_F(InterfaceBundleTest, ExampleUsage) {
InterfaceBundle bundle;
RemoteInterfaces interfaces(bundle.CreateRemote());
ASSERT_TRUE(
bundle.AddInterface<test::mojom::StringInterface>(&mock_interface_));
mojo::Remote<test::mojom::StringInterface> remote;
interfaces.BindNewPipe(&remote);
ASSERT_TRUE(remote.is_bound());
std::string s = "Hello, world!";
EXPECT_CALL(mock_interface_, StringMethod(s));
remote->StringMethod(s);
task_environment_.RunUntilIdle();
auto bad_remote = interfaces.CreateRemote<test::mojom::IntInterface>();
ASSERT_TRUE(bad_remote.is_bound());
ASSERT_TRUE(bad_remote.is_connected());
task_environment_.RunUntilIdle();
ASSERT_FALSE(bad_remote.is_connected());
}
TEST_F(InterfaceBundleTest, Lifetime) {
MockErrorHandler error_handler_;
mojo::Remote<test::mojom::StringInterface> remote;
{
InterfaceBundle bundle;
RemoteInterfaces interfaces(bundle.CreateRemote());
ASSERT_TRUE(
bundle.AddInterface<test::mojom::StringInterface>(&mock_interface_));
interfaces.BindNewPipe(&remote);
std::string s = "Hello, world!";
EXPECT_CALL(mock_interface_, StringMethod(s));
remote->StringMethod(s);
task_environment_.RunUntilIdle();
remote.set_disconnect_handler(base::BindOnce(
&MockErrorHandler::OnError, base::Unretained(&error_handler_)));
EXPECT_CALL(error_handler_, OnError()).Times(1);
}
task_environment_.RunUntilIdle();
ASSERT_FALSE(remote.is_connected());
}
TEST_F(InterfaceBundleTest, LateBinding) {
InterfaceBundle bundle;
RemoteInterfaces interfaces;
ASSERT_TRUE(
bundle.AddInterface<test::mojom::StringInterface>(&mock_interface_));
mojo::Remote<test::mojom::StringInterface> remote;
interfaces.BindNewPipe(&remote);
std::string s = "Hello, world!";
EXPECT_CALL(mock_interface_, StringMethod(s)).Times(0);
remote->StringMethod(s);
remote->StringMethod(s);
remote->StringMethod(s);
task_environment_.RunUntilIdle();
EXPECT_CALL(mock_interface_, StringMethod(s)).Times(3);
interfaces.SetProvider(bundle.CreateRemote());
task_environment_.RunUntilIdle();
}
}