blob: 5d2d7f9fc1a9177f2f3dd1ca5d91c0e638300a9a [file] [log] [blame]
// Copyright 2020 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 <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/session.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <gtest/gtest.h>
#include "src/ui/scenic/lib/input/tests/util.h"
// These tests exercise InputSystem logic during startup, e.g. potential race conditions.
namespace lib_ui_input_tests {
namespace {
using fuchsia::ui::input::InputEvent;
using fuchsia::ui::input::PointerEventPhase;
using fuchsia::ui::input::PointerEventType;
// Class fixture for TEST_F. Sets up a 5x5 "display" for GfxSystem.
class StartupTest : public InputSystemTest {
protected:
uint32_t test_display_width_px() const override { return 5; }
uint32_t test_display_height_px() const override { return 5; }
// Injects an arbitrary input event using the legacy injection API.
// Uses a new pointer on each injection to minimize conteracting between different injections.
void InjectFreshEvent(scenic::Session* session, uint32_t compositor_id) {
PointerCommandGenerator pointer(compositor_id, /*device id*/ 1,
/*pointer id*/ ++last_pointer_id_, PointerEventType::TOUCH);
session->Enqueue(pointer.Add(2.5, 2.5));
}
uint32_t last_pointer_id_ = 0;
};
// This test builds up a scene piece by piece, injecting input at every point to confirm
// that there is no crash.
TEST_F(StartupTest, LegacyInjectBeforeSceneSetupComplete_ShouldNotCrash) {
static uint32_t kFakeCompositorId = 321241;
SessionWrapper root_session(scenic());
scenic::Session* const session = root_session.session();
auto [v, vh] = scenic::ViewTokenPair::New();
SessionWrapper client = CreateClient("view", std::move(v));
scenic::ViewHolder holder(session, std::move(vh), "holder");
holder.SetViewProperties(k5x5x1);
// Empty.
RequestToPresent(session);
InjectFreshEvent(session, kFakeCompositorId);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
// Only a Scene object.
scenic::Scene scene(session);
RequestToPresent(session);
InjectFreshEvent(session, kFakeCompositorId);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
// Attach the child to the scene now that we have one.
scene.AddChild(holder);
scenic::Camera camera(scene);
RequestToPresent(session);
InjectFreshEvent(session, kFakeCompositorId);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
scenic::Renderer renderer(session);
RequestToPresent(session);
InjectFreshEvent(session, kFakeCompositorId);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
renderer.SetCamera(camera);
RequestToPresent(session);
InjectFreshEvent(session, kFakeCompositorId);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
scenic::Compositor compositor(session);
RequestToPresent(session);
const uint32_t compositor_id = compositor.id();
InjectFreshEvent(session, kFakeCompositorId); // With fake compositor id.
InjectFreshEvent(session, compositor_id); // With real compositor id.
RunLoopUntilIdle(); // Should not crash.
scenic::LayerStack layer_stack(session);
RequestToPresent(session);
InjectFreshEvent(session, compositor_id);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
compositor.SetLayerStack(layer_stack);
RequestToPresent(session);
InjectFreshEvent(session, compositor_id);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
scenic::Layer layer(session);
RequestToPresent(session);
InjectFreshEvent(session, compositor_id);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
layer_stack.AddLayer(layer);
RequestToPresent(session);
InjectFreshEvent(session, compositor_id);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
layer.SetRenderer(renderer);
RequestToPresent(session);
InjectFreshEvent(session, compositor_id);
RunLoopUntilIdle(); // Should not crash.
EXPECT_TRUE(client.events().empty());
layer.SetSize(10, 10);
RequestToPresent(session);
InjectFreshEvent(session, compositor_id);
RunLoopUntilIdle(); // Should not crash.
// Should now have received the final event.
EXPECT_FALSE(client.events().empty());
}
} // namespace
} // namespace lib_ui_input_tests