blob: af32d709dc29e64f1c0c2946be35aefdbfdcb19c [file] [log] [blame]
// Copyright 2021 The Fuchsia 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 "src/ui/input/lib/injector/injector_config_setup.h"
#include <fuchsia/ui/pointerinjector/configuration/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/sys/cpp/testing/component_context_provider.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <zircon/status.h>
#include <gtest/gtest.h>
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
namespace input {
namespace {
zx_koid_t ExtractKoid(const fuchsia::ui::views::ViewRef& view_ref) {
zx_info_handle_basic_t info{};
if (view_ref.reference.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr) !=
ZX_OK) {
return ZX_KOID_INVALID; // no info
}
return info.koid;
}
class InjectorConfigSetupTest : public gtest::TestLoopFixture {
protected:
sys::testing::ComponentContextProvider context_provider_;
};
TEST_F(InjectorConfigSetupTest, GetViewRefs) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Connect to the Setup service exposed by InjectorConfigSetup.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
// Assert GetViewRefs() returns the correct viewrefs.
bool checked_view_refs{false};
auto context_view_ref_koid = ExtractKoid(context_view_ref);
auto target_view_ref_koid = ExtractKoid(target_view_ref);
setup_proxy->GetViewRefs(
[&](fuchsia::ui::views::ViewRef context, fuchsia::ui::views::ViewRef target) {
EXPECT_EQ(ExtractKoid(context), context_view_ref_koid);
EXPECT_EQ(ExtractKoid(target), target_view_ref_koid);
checked_view_refs = true;
});
RunLoopUntilIdle();
EXPECT_TRUE(checked_view_refs);
}
TEST_F(InjectorConfigSetupTest, WatchViewport_ViewportExists) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Set a viewport.
fuchsia::ui::pointerinjector::Viewport viewport;
viewport.set_extents({{{0, 0}, {100, 100}}});
viewport.set_viewport_to_context_transform({1, 0, 0, 0, 1, 0, 0, 0, 1});
pointer_injector_setup.UpdateViewport(fidl::Clone(viewport));
// Connect to the Setup service exposed by InjectorConfigSetup.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
// Assert WatchViewport() returns the correct viewport.
bool watch_viewport_completed{false};
setup_proxy->WatchViewport([&](fuchsia::ui::pointerinjector::Viewport watched_viewport) {
EXPECT_EQ(watched_viewport.extents(), viewport.extents());
EXPECT_EQ(watched_viewport.viewport_to_context_transform(),
viewport.viewport_to_context_transform());
watch_viewport_completed = true;
});
RunLoopUntilIdle();
EXPECT_TRUE(watch_viewport_completed);
}
TEST_F(InjectorConfigSetupTest, WatchViewport_NoViewport) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Connect to the Setup service exposed by InjectorConfigSetup.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
// Call WatchViewport() before setting a viewport.
bool watch_viewport_completed{false};
fuchsia::ui::pointerinjector::Viewport watched_viewport;
setup_proxy->WatchViewport([&](fuchsia::ui::pointerinjector::Viewport viewport) {
watched_viewport = std::move(viewport);
watch_viewport_completed = true;
});
// Set a viewport.
fuchsia::ui::pointerinjector::Viewport viewport;
viewport.set_extents({{{0, 0}, {100, 100}}});
viewport.set_viewport_to_context_transform({1, 0, 0, 0, 1, 0, 0, 0, 1});
pointer_injector_setup.UpdateViewport(fidl::Clone(viewport));
RunLoopUntilIdle();
EXPECT_TRUE(watch_viewport_completed);
// Assert that the viewports match.
EXPECT_EQ(watched_viewport.extents(), viewport.extents());
EXPECT_EQ(watched_viewport.viewport_to_context_transform(),
viewport.viewport_to_context_transform());
}
TEST_F(InjectorConfigSetupTest, WatchViewport_ViewportUpdated) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Set a viewport.
fuchsia::ui::pointerinjector::Viewport viewport;
viewport.set_extents({{{0, 0}, {100, 100}}});
viewport.set_viewport_to_context_transform({1, 0, 0, 0, 1, 0, 0, 0, 1});
pointer_injector_setup.UpdateViewport(std::move(viewport));
// Connect to the Setup service exposed by InjectorConfigSetup.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
// Update the viewport.
fuchsia::ui::pointerinjector::Viewport updated_viewport;
updated_viewport.set_extents({{{200, 200}, {300, 300}}});
updated_viewport.set_viewport_to_context_transform({0, 0, 1, 0, 1, 0, 1, 0, 0});
pointer_injector_setup.UpdateViewport(fidl::Clone(updated_viewport));
// Assert WatchViewport() returns the updated viewport.
bool watch_viewport_completed{false};
setup_proxy->WatchViewport([&](fuchsia::ui::pointerinjector::Viewport watched_viewport) {
EXPECT_EQ(watched_viewport.extents(), updated_viewport.extents());
EXPECT_EQ(watched_viewport.viewport_to_context_transform(),
updated_viewport.viewport_to_context_transform());
watch_viewport_completed = true;
});
RunLoopUntilIdle();
EXPECT_TRUE(watch_viewport_completed);
}
TEST_F(InjectorConfigSetupTest, WatchViewport_CalledTwice) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Connect to the Setup service exposed by InjectorConfigSetup.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
bool setup_connection_error{false};
setup_proxy.set_error_handler([&setup_connection_error](zx_status_t status) {
EXPECT_EQ(status, ZX_ERR_BAD_STATE);
setup_connection_error = true;
});
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
// Assert WatchViewport() fails when called twice.
setup_proxy->WatchViewport([&](fuchsia::ui::pointerinjector::Viewport) {});
setup_proxy->WatchViewport([&](fuchsia::ui::pointerinjector::Viewport) {});
RunLoopUntilIdle();
EXPECT_TRUE(setup_connection_error);
}
TEST_F(InjectorConfigSetupTest, WatchViewport_ReconnectWithOutstandingCall) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Connect to the Setup service exposed by InjectorConfigSetup.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
// Disconnect after calling WatchViewport().
setup_proxy->WatchViewport([&](fuchsia::ui::pointerinjector::Viewport) {});
setup_proxy.Unbind();
RunLoopUntilIdle();
// Set a viewport so WatchViewport() returns.
fuchsia::ui::pointerinjector::Viewport viewport;
viewport.set_extents({{{0, 0}, {100, 100}}});
viewport.set_viewport_to_context_transform({1, 0, 0, 0, 1, 0, 0, 0, 1});
pointer_injector_setup.UpdateViewport(std::move(viewport));
// Reconnect and call to WatchViewport() should succeed.
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
bool watched_viewport{false};
setup_proxy->WatchViewport(
[&](fuchsia::ui::pointerinjector::Viewport) { watched_viewport = true; });
RunLoopUntilIdle();
EXPECT_TRUE(watched_viewport);
}
TEST_F(InjectorConfigSetupTest, WatchViewport_ReconnectWithoutOutstandingCall) {
// Create InjectorConfigSetup.
auto [context_control_ref, context_view_ref] = scenic::ViewRefPair::New();
auto [target_control_ref, target_view_ref] = scenic::ViewRefPair::New();
InjectorConfigSetup pointer_injector_setup(
context_provider_.context(), fidl::Clone(context_view_ref), fidl::Clone(target_view_ref));
// Connect to the Setup service exposed by InjectorConfigSetup and immediately disconnect.
fuchsia::ui::pointerinjector::configuration::SetupPtr setup_proxy;
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
setup_proxy.Unbind();
RunLoopUntilIdle();
// Set a viewport so WatchViewport() returns.
fuchsia::ui::pointerinjector::Viewport viewport;
viewport.set_extents({{{0, 0}, {100, 100}}});
viewport.set_viewport_to_context_transform({1, 0, 0, 0, 1, 0, 0, 0, 1});
pointer_injector_setup.UpdateViewport(std::move(viewport));
// Reconnect and call to WatchViewport() should succeed.
context_provider_.ConnectToPublicService(setup_proxy.NewRequest());
bool watched_viewport{false};
setup_proxy->WatchViewport(
[&](fuchsia::ui::pointerinjector::Viewport) { watched_viewport = true; });
RunLoopUntilIdle();
EXPECT_TRUE(watched_viewport);
}
} // namespace
} // namespace input