#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom-features.h"
#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom-forward.h"
#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom-shared.h"
#include "mojo/public/cpp/bindings/tests/feature_unittest.test-mojom.h"
#include <utility>
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/bindings/service_factory.h"
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
#include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
#include "mojo/public/cpp/system/functions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo::test::feature_unittest {
namespace {
class DefaultDeniedImpl : public mojom::DefaultDenied { … };
class OtherDeniedImpl : public mojom::OtherDenied { … };
class OtherAllowedImpl : public mojom::OtherAllowed { … };
class DefaultDeniedSelfOwnedImpl : public mojom::DefaultDenied { … };
class DefaultAllowedSelfOwnedImpl : public mojom::DefaultAllowed { … };
class DefaultAllowedImpl : mojom::DefaultAllowed { … };
class FeaturesOnMethodsImpl : public mojom::FeaturesOnMethods { … };
class PassesInterfacesImpl : public mojom::PassesInterfaces { … };
}
class FeatureBindingsTest : public BindingsTestBase { … };
TEST(…) {
EXPECT_TRUE(…);
EXPECT_FALSE(…);
}
TEST(…) {
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "TestFeatureOn");
EXPECT_FALSE(…);
EXPECT_TRUE(…);
}
TEST_P(…) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::DefaultAllowed> remote;
DefaultAllowedImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(…);
base::RunLoop run_loop;
remote->GetInt(base::BindLambdaForTesting([&](int) { run_loop.Quit(); }));
run_loop.Run();
EXPECT_FALSE(…);
}
TEST_P(…) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::OtherAllowed> remote;
OtherAllowedImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(…);
base::RunLoop run_loop;
remote->GetInt(base::BindLambdaForTesting([&](int) { run_loop.Quit(); }));
run_loop.Run();
EXPECT_FALSE(…);
}
TEST_P(…) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::FeaturesOnMethods> remote;
EXPECT_FALSE(…);
FeaturesOnMethodsImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(…);
base::RunLoop run_loop;
remote->DefaultAllowed(
base::BindLambdaForTesting([&](int) { run_loop.Quit(); }));
run_loop.Run();
base::RunLoop run_loop2;
remote->Normal(base::BindLambdaForTesting([&](int) { run_loop2.Quit(); }));
run_loop2.Run();
EXPECT_FALSE(…);
}
TEST_P(…) {
if (GetParam() == mojo::BindingsTestSerializationMode::kNeverSerialize) {
return;
}
bool called = false;
bool called_disconnect = false;
base::RunLoop run_loop;
Remote<mojom::FeaturesOnMethods> remote;
auto pending_receiver = remote.BindNewPipeAndPassReceiver();
remote.set_disconnect_handler(base::BindLambdaForTesting([&] {
called_disconnect = true;
run_loop.Quit();
}));
{
base::test::ScopedFeatureList feature_list;
feature_list.InitFromCommandLine("TestFeatureOff", "");
remote->DefaultDenied(
base::BindLambdaForTesting([&](int) { called = true; }));
}
FeaturesOnMethodsImpl impl(std::move(pending_receiver));
run_loop.Run();
EXPECT_FALSE(…);
EXPECT_TRUE(…);
}
TEST_P(…) {
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] { error = true; }));
Remote<mojom::PassesInterfaces> remote;
EXPECT_FALSE(…);
PassesInterfacesImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_TRUE(…);
{
base::RunLoop run_loop;
MessagePipe pipe;
PendingRemote<mojom::DefaultAllowed> allowed_pending_remote(
std::move(pipe.handle0), 0);
PendingReceiver<mojom::DefaultAllowed> allowed_pending_receiver(
std::move(pipe.handle1));
bool cb_val = false;
remote->PassPendingOptionalRemoteAllowed(
std::move(allowed_pending_remote),
base::BindLambdaForTesting([&](bool val) {
cb_val = val;
run_loop.Quit();
}));
DefaultAllowedImpl allowed_impl(std::move(allowed_pending_receiver));
run_loop.Run();
ASSERT_TRUE(…);
}
{
base::RunLoop run_loop;
MessagePipe pipe;
PendingRemote<mojom::DefaultAllowed> allowed_pending_remote(
std::move(pipe.handle0), 0);
PendingReceiver<mojom::DefaultAllowed> allowed_pending_receiver(
std::move(pipe.handle1));
bool cb_val = false;
remote->PassPendingOptionalReceiverAllowed(
std::move(allowed_pending_receiver));
Remote<mojom::DefaultAllowed> allowed(std::move(allowed_pending_remote));
allowed->GetInt(base::BindLambdaForTesting([&](int val) {
cb_val = val == 1;
run_loop.Quit();
}));
run_loop.Run();
ASSERT_TRUE(…);
}
}
TEST_P(…) {
Remote<mojom::DefaultAllowed> remote_a;
Remote<mojom::DefaultAllowed> remote_b;
DefaultAllowedImpl impl_a(remote_a.BindNewPipeAndPassReceiver());
DefaultAllowedImpl impl_b(remote_b.BindNewPipeAndPassReceiver());
PendingRemote<mojom::DefaultAllowed> pending_remote_c;
auto pending_receiver_c = pending_remote_c.InitWithNewPipeAndPassReceiver();
PendingRemote<mojom::DefaultAllowed> pending_remote_d;
auto pending_receiver_d = pending_remote_d.InitWithNewPipeAndPassReceiver();
auto impl_c = std::make_unique<DefaultAllowedSelfOwnedImpl>();
auto impl_d = std::make_unique<DefaultAllowedSelfOwnedImpl>();
ReceiverSet<mojom::DefaultAllowed> receiver_set;
receiver_set.Add(impl_c.get(), std::move(pending_receiver_c));
receiver_set.Add(impl_d.get(), std::move(pending_receiver_d));
RemoteSet<mojom::DefaultAllowed> remote_set;
remote_set.Add(std::move(remote_a));
remote_set.Add(std::move(remote_b));
remote_set.Add(std::move(pending_remote_c));
remote_set.Add(std::move(pending_remote_d));
}
TEST_P(…) {
ServiceFactory services;
MessagePipe pipe_allowed;
MessagePipe pipe_denied;
services.Add(DefaultAllowedImpl::RunService);
services.Add(DefaultDeniedImpl::RunService);
GenericPendingReceiver gpr_allowed(mojom::DefaultAllowed::Name_,
std::move(pipe_allowed.handle0));
GenericPendingReceiver gpr_denied(mojom::DefaultDenied::Name_,
std::move(pipe_denied.handle0));
EXPECT_TRUE(…);
EXPECT_FALSE(…);
}
#if !DCHECK_IS_ON()
TEST_P(FeatureBindingsTest, InertPendingRemoteWontInit) {
PendingRemote<mojom::DefaultDenied> pending_remote;
EXPECT_FALSE(pending_remote);
PendingReceiver<mojom::DefaultDenied> pending_receiver =
pending_remote.InitWithNewPipeAndPassReceiver();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, InertPendingReceiverWontInit) {
PendingReceiver<mojom::DefaultDenied> pending_receiver;
EXPECT_FALSE(pending_receiver);
PendingRemote<mojom::DefaultDenied> pending_remote =
pending_receiver.InitWithNewPipeAndPassRemote();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, InertPendingAssociatedRemoteWontInit) {
PendingAssociatedRemote<mojom::DefaultDenied> pending_remote;
EXPECT_FALSE(pending_remote);
PendingAssociatedReceiver<mojom::DefaultDenied> pending_receiver =
pending_remote.InitWithNewEndpointAndPassReceiver();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, InertPendingAssociatedReceiverWontInit) {
PendingAssociatedReceiver<mojom::DefaultDenied> pending_receiver;
EXPECT_FALSE(pending_receiver);
PendingAssociatedRemote<mojom::DefaultDenied> pending_remote =
pending_receiver.InitWithNewEndpointAndPassRemote();
EXPECT_FALSE(pending_receiver);
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, RemoteWontBindNewPipe) {
Remote<mojom::DefaultDenied> remote;
EXPECT_FALSE(remote);
PendingReceiver<mojom::DefaultDenied> pending_receiver =
remote.BindNewPipeAndPassReceiver();
EXPECT_FALSE(pending_receiver);
}
TEST_P(FeatureBindingsTest, RemoteWontBindPendingRemote) {
MessagePipe pipe;
PendingRemote<mojom::DefaultDenied> pending_remote(std::move(pipe.handle0),
0);
Remote<mojom::DefaultDenied> remote;
EXPECT_FALSE(remote);
remote.Bind(std::move(pending_remote));
EXPECT_FALSE(remote);
}
TEST_P(FeatureBindingsTest, AssociatedRemoteWontBind) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver;
{
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "");
pa_receiver = pa_remote.InitWithNewEndpointAndPassReceiver();
}
EXPECT_TRUE(pa_remote);
AssociatedRemote<mojom::DefaultDenied> a_remote;
a_remote.Bind(std::move(pa_remote));
EXPECT_FALSE(a_remote);
}
TEST_P(FeatureBindingsTest, AssociatedRemoteWontBindNewEndpoint) {
AssociatedRemote<mojom::DefaultDenied> a_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
a_remote.BindNewEndpointAndPassReceiver();
EXPECT_FALSE(a_remote);
EXPECT_FALSE(pa_receiver);
}
TEST_P(FeatureBindingsTest, AssociatedRemoteWontBindDedicated) {
AssociatedRemote<mojom::DefaultDenied> a_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
a_remote.BindNewEndpointAndPassDedicatedReceiver();
EXPECT_FALSE(a_remote);
EXPECT_FALSE(pa_receiver);
}
TEST_P(FeatureBindingsTest, ReceiverWontBindNewPipe) {
DefaultDeniedImpl impl;
PendingRemote<mojom::DefaultDenied> pending_remote =
impl.receiver().BindNewPipeAndPassRemote();
EXPECT_FALSE(pending_remote);
}
TEST_P(FeatureBindingsTest, ReceiverWontBindPendingReceiver) {
MessagePipe pipe;
PendingReceiver<mojom::DefaultDenied> pending_receiver(
std::move(pipe.handle0));
EXPECT_TRUE(pending_receiver);
DefaultDeniedImpl impl(std::move(pending_receiver));
EXPECT_FALSE(impl.receiver().is_bound());
}
TEST_P(FeatureBindingsTest, AssociatedReceiverWontBind) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
pa_remote.InitWithNewEndpointAndPassReceiver();
DefaultDeniedSelfOwnedImpl impl;
AssociatedReceiver<mojom::DefaultDenied> a_receiver(&impl);
a_receiver.Bind(std::move(pa_receiver), nullptr);
EXPECT_FALSE(a_receiver.is_bound());
}
TEST_P(FeatureBindingsTest, AssociatedReceiverWontBindNewEndpoint) {
DefaultDeniedSelfOwnedImpl impl;
AssociatedReceiver<mojom::DefaultDenied> a_receiver(&impl);
auto a_remote = a_receiver.BindNewEndpointAndPassRemote(nullptr);
EXPECT_FALSE(a_receiver);
EXPECT_FALSE(a_remote);
}
TEST_P(FeatureBindingsTest, AssociatedReceiverWontBindDedicated) {
DefaultDeniedSelfOwnedImpl impl;
AssociatedReceiver<mojom::DefaultDenied> a_receiver(&impl);
auto a_remote = a_receiver.BindNewEndpointAndPassDedicatedRemote();
EXPECT_FALSE(a_receiver);
EXPECT_FALSE(a_remote);
}
TEST_P(FeatureBindingsTest, SelfOwnedReceiver) {
MessagePipe pipe;
PendingReceiver<mojom::DefaultDenied> pending_receiver(
std::move(pipe.handle0));
auto impl = std::make_unique<DefaultDeniedSelfOwnedImpl>();
auto weak_ref =
MakeSelfOwnedReceiver(std::move(impl), std::move(pending_receiver));
EXPECT_FALSE(weak_ref);
}
TEST_P(FeatureBindingsTest, SelfOwnedAssociatedReceiver) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
pa_remote.InitWithNewEndpointAndPassReceiver();
auto impl = std::make_unique<DefaultDeniedSelfOwnedImpl>();
auto weak_ref =
MakeSelfOwnedAssociatedReceiver(std::move(impl), std::move(pa_receiver));
EXPECT_FALSE(weak_ref);
}
TEST_P(FeatureBindingsTest, SharedRemoteWontBindNewPipe) {
SharedRemote<mojom::DefaultDenied> s_remote;
EXPECT_FALSE(s_remote);
PendingReceiver<mojom::DefaultDenied> p_receiver =
s_remote.BindNewPipeAndPassReceiver();
EXPECT_FALSE(s_remote);
EXPECT_FALSE(p_receiver);
}
TEST_P(FeatureBindingsTest, SharedRemoteWontBind) {
PendingRemote<mojom::DefaultDenied> pa_remote;
PendingReceiver<mojom::DefaultDenied> pa_receiver;
{
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "");
pa_receiver = pa_remote.InitWithNewPipeAndPassReceiver();
}
EXPECT_TRUE(pa_remote);
SharedRemote<mojom::DefaultDenied> s_remote;
s_remote.Bind(std::move(pa_remote), nullptr);
EXPECT_FALSE(s_remote);
}
TEST_P(FeatureBindingsTest, SharedAssociatedRemoteWontBindNewEndpoint) {
SharedAssociatedRemote<mojom::DefaultDenied> sa_remote;
EXPECT_FALSE(sa_remote);
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver =
sa_remote.BindNewEndpointAndPassReceiver();
EXPECT_FALSE(sa_remote);
EXPECT_FALSE(pa_receiver);
}
TEST_P(FeatureBindingsTest, SharedAssociatedRemoteWontBind) {
PendingAssociatedRemote<mojom::DefaultDenied> pa_remote;
PendingAssociatedReceiver<mojom::DefaultDenied> pa_receiver;
{
base::test::ScopedFeatureList feature_list1;
feature_list1.InitFromCommandLine("TestFeatureOff", "");
pa_receiver = pa_remote.InitWithNewEndpointAndPassReceiver();
}
EXPECT_TRUE(pa_remote);
SharedAssociatedRemote<mojom::DefaultDenied> sa_remote;
sa_remote.Bind(std::move(pa_remote), nullptr);
EXPECT_FALSE(sa_remote);
}
TEST_P(FeatureBindingsTest, GenericPendingReceivers) {
MessagePipe pipe_a;
ScopedInterfaceEndpointHandle end_a;
ScopedInterfaceEndpointHandle end_b;
ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&end_a, &end_b);
GenericPendingReceiver gpr_allowed(mojom::DefaultAllowed::Name_,
std::move(pipe_a.handle0));
GenericPendingReceiver gpr_denied(mojom::DefaultDenied::Name_,
std::move(pipe_a.handle1));
GenericPendingAssociatedReceiver gpar_allowed(mojom::DefaultAllowed::Name_,
std::move(end_a));
GenericPendingAssociatedReceiver gpar_denied(mojom::DefaultDenied::Name_,
std::move(end_b));
auto p_allowed = gpr_allowed.As<mojom::DefaultAllowed>();
auto p_denied = gpr_denied.As<mojom::DefaultDenied>();
auto pa_allowed = gpar_allowed.As<mojom::DefaultAllowed>();
auto pa_denied = gpar_denied.As<mojom::DefaultDenied>();
EXPECT_TRUE(p_allowed);
EXPECT_TRUE(pa_allowed);
EXPECT_FALSE(p_denied);
EXPECT_FALSE(pa_denied);
}
TEST_P(FeatureBindingsTest, PassesOptionalInterfacesRemoteDenied) {
if (GetParam() == BindingsTestSerializationMode::kNeverSerialize) {
return;
}
Remote<mojom::PassesInterfaces> remote;
PassesInterfacesImpl impl(remote.BindNewPipeAndPassReceiver());
base::RunLoop run_loop;
MessagePipe pipe;
PendingRemote<mojom::DefaultDenied> denied_pending_remote(
std::move(pipe.handle0), 0);
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] {
error = true;
run_loop.Quit();
}));
bool called_empty = false;
remote->PassPendingOptionalRemoteDisabled(
std::move(denied_pending_remote),
base::BindLambdaForTesting([&](bool val) {
called_empty = val;
run_loop.Quit();
}));
run_loop.Run();
ASSERT_FALSE(error);
ASSERT_TRUE(called_empty);
}
TEST_P(FeatureBindingsTest, PassesOptionalInterfacesReceiverDenied) {
if (GetParam() == mojo::BindingsTestSerializationMode::kNeverSerialize) {
return;
}
Remote<mojom::PassesInterfaces> remote;
PassesInterfacesImpl impl(remote.BindNewPipeAndPassReceiver());
base::RunLoop run_loop;
MessagePipe pipe;
PendingReceiver<mojom::DefaultDenied> denied_pending_receiver(
std::move(pipe.handle1));
bool error = false;
SetErrorHandler(base::BindLambdaForTesting([&] {
error = true;
run_loop.Quit();
}));
bool called_empty = false;
remote->PassPendingOptionalReceiverDisabled(
std::move(denied_pending_receiver),
base::BindLambdaForTesting([&](bool val) {
called_empty = val;
run_loop.Quit();
}));
run_loop.Run();
ASSERT_FALSE(error);
ASSERT_TRUE(called_empty);
}
TEST_P(FeatureBindingsTest, RemoteWontBindNewPipeImported) {
Remote<mojom::OtherDenied> remote;
PendingReceiver<mojom::OtherDenied> pending_receiver =
remote.BindNewPipeAndPassReceiver();
EXPECT_FALSE(pending_receiver);
}
TEST_P(FeatureBindingsTest, ReceiverWontBindPendingReceiverImported) {
MessagePipe pipe;
PendingReceiver<mojom::OtherDenied> pending_receiver(std::move(pipe.handle0));
OtherDeniedImpl impl(std::move(pending_receiver));
EXPECT_FALSE(impl.receiver().is_bound());
}
TEST_P(FeatureBindingsTest, ReceiverSetDenied) {
MessagePipe pipe_a;
PendingReceiver<mojom::DefaultDenied> pending_receiver_a(
std::move(pipe_a.handle0));
auto impl = std::make_unique<DefaultDeniedSelfOwnedImpl>();
ReceiverSet<mojom::DefaultDenied> receiver_set;
EXPECT_EQ(receiver_set.Add(impl.get(), std::move(pending_receiver_a)),
std::nullopt);
}
TEST_P(FeatureBindingsTest, RemoteSetDenied) {
PendingRemote<mojom::DefaultDenied> pending_remote;
auto pending_receiver = pending_remote.InitWithNewPipeAndPassReceiver();
RemoteSet<mojom::DefaultDenied> remote_set;
EXPECT_EQ(remote_set.Add(std::move(pending_remote)), std::nullopt);
}
#endif
#if defined(GTEST_HAS_DEATH_TEST) && !BUILDFLAG(IS_ANDROID)
using FeatureBindingsDeathTest = FeatureBindingsTest;
TEST_P(…) {
bool called = false;
Remote<mojom::FeaturesOnMethods> remote;
FeaturesOnMethodsImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_DEATH(…);
EXPECT_FALSE(…);
}
TEST_P(…) {
int result = 0;
Remote<mojom::FeaturesOnMethods> remote;
FeaturesOnMethodsImpl impl(remote.BindNewPipeAndPassReceiver());
EXPECT_DEATH(…);
EXPECT_EQ(…);
}
TEST_P(…) {
bool called = false;
AssociatedRemote<mojom::FeaturesOnMethods> remote;
FeaturesOnMethodsImpl impl(remote.BindNewEndpointAndPassDedicatedReceiver());
EXPECT_DEATH(…);
EXPECT_FALSE(…);
}
INSTANTIATE_TEST_SUITE_P(…);
#endif
INSTANTIATE_TEST_SUITE_P(…);
}