blob: 70403712c6b132829655433f8916562e5fc4cc01 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_WAYLAND_TEST_H_
#define UI_OZONE_PLATFORM_WAYLAND_TEST_WAYLAND_TEST_H_
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/buildflags.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/ozone/layout/keyboard_layout_engine.h"
#include "ui/ozone/common/features.h"
#include "ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h"
#include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/test/mock_wayland_platform_window_delegate.h"
#include "ui/ozone/platform/wayland/test/scoped_wl_array.h"
#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
#if BUILDFLAG(USE_XKBCOMMON)
#include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h"
#endif
namespace ui {
class ScopedKeyboardLayoutEngine;
class WaylandScreen;
// WaylandTest is a base class that sets up a display, window, and test server,
// and allows easy synchronization between them.
class WaylandTestBase {
public:
explicit WaylandTestBase(wl::ServerConfig config);
WaylandTestBase(const WaylandTestBase&) = delete;
WaylandTestBase& operator=(const WaylandTestBase&) = delete;
~WaylandTestBase();
void SetUp();
void TearDown();
// Posts 'callback' or 'closure' to run on the server thread; blocks till the
// callable is run and all pending Wayland requests and events are delivered.
// Note: This by default uses base::RunLoops which causes all posted tasks,
// including tasks posted with a delay, to run during this call before all
// server's events are processed by the client.
// The 'no_nested_runloops' parameter can be used to not use runloops for
// testing code that posts delayed tasks and the delay can be controlled in
// the test without them being executed unexpectedly during this call.
void PostToServerAndWait(
base::OnceCallback<void(wl::TestWaylandServerThread* server)> callback,
bool no_nested_runloops = true);
void PostToServerAndWait(base::OnceClosure closure,
bool no_nested_runloops = true);
// Similar to the two methods above, but provides the convenience of using a
// capturing lambda directly.
template <
typename Lambda,
typename = std::enable_if_t<
std::is_invocable_r_v<void, Lambda, wl::TestWaylandServerThread*> ||
std::is_invocable_r_v<void, Lambda>>>
void PostToServerAndWait(Lambda&& lambda, bool no_nested_runloops = true) {
PostToServerAndWait(base::BindLambdaForTesting(std::move(lambda)),
no_nested_runloops);
}
// Convenience wrapper function for WaylandConnectionTestApi::SyncDisplay.
void SyncDisplay();
protected:
// Disables client-server sync during the teardown. Used by tests that
// intentionally spoil the client-server communication.
void DisableSyncOnTearDown();
void SetPointerFocusedWindow(WaylandWindow* window);
void SetKeyboardFocusedWindow(WaylandWindow* window);
// Sends configure event for the |surface_id|. Please note that |surface_id|
// must be an id of the wl_surface that has xdg_surface role.
void SendConfigureEvent(uint32_t surface_id,
const gfx::Size& size,
const wl::ScopedWlArray& states,
std::optional<uint32_t> serial = std::nullopt);
// Sends XDG_TOPLEVEL_STATE_ACTIVATED to associated with `window_deletate` and
// has xdg surface role with width and height set to 0, which results in
// asking the client to set the width and height of the surface. The client
// test may pass |serial| that will be used to activate the surface.
void ActivateSurface(MockWaylandPlatformWindowDelegate& window_delegate,
std::optional<uint32_t> serial = std::nullopt);
// Assuming that the window associated with `window_delegate` has just
// received the first configure sequence and is waiting for a non-null buffer
// to be attached, this emulates such buffer attachment and verifies the
// expectations.
void MapSurface(MockWaylandPlatformWindowDelegate& window_delegate);
// A helper method that sets up the XKB configuration for tests that require
// it.
// Does nothing if XkbCommon is not used.
void MaybeSetUpXkb();
// A helper method to ensure that information for all displays are populated
// and ready.
void WaitForAllDisplaysReady();
// Creates a Wayland window with the specified delegate, type, and bounds.
std::unique_ptr<WaylandWindow> CreateWaylandWindowWithParams(
PlatformWindowType type,
const gfx::Rect bounds,
MockWaylandPlatformWindowDelegate* delegate,
gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget);
base::test::TaskEnvironment task_environment_;
wl::TestWaylandServerThread server_;
#if BUILDFLAG(USE_XKBCOMMON)
XkbEvdevCodes xkb_evdev_code_converter_;
#endif
::testing::NiceMock<MockWaylandPlatformWindowDelegate> delegate_;
std::unique_ptr<ScopedKeyboardLayoutEngine> scoped_keyboard_layout_engine_;
std::unique_ptr<WaylandSurfaceFactory> surface_factory_;
std::unique_ptr<WaylandBufferManagerGpu> buffer_manager_gpu_;
std::unique_ptr<WaylandConnection> connection_;
std::unique_ptr<WaylandScreen> screen_;
std::unique_ptr<WaylandWindow> window_;
gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
std::vector<base::test::FeatureRef> enabled_features_{
ui::kWaylandOverlayDelegation};
std::vector<base::test::FeatureRef> disabled_features_;
private:
bool initialized_ = false;
std::unique_ptr<KeyboardLayoutEngine> keyboard_layout_engine_;
base::test::ScopedFeatureList feature_list_;
};
// Version of WaylandTestBase that uses parametrised tests (TEST_P).
class WaylandTest : public WaylandTestBase,
public ::testing::TestWithParam<wl::ServerConfig> {
public:
WaylandTest();
WaylandTest(const WaylandTest&) = delete;
WaylandTest& operator=(const WaylandTest&) = delete;
~WaylandTest() override;
void SetUp() override;
void TearDown() override;
};
// Version of WaylandTest that uses simple test fixtures (TEST_F).
class WaylandTestSimple : public WaylandTestBase, public ::testing::Test {
public:
WaylandTestSimple();
explicit WaylandTestSimple(wl::ServerConfig);
WaylandTestSimple(const WaylandTestSimple&) = delete;
WaylandTestSimple& operator=(const WaylandTestSimple&) = delete;
~WaylandTestSimple() override;
void SetUp() override;
void TearDown() override;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_WAYLAND_TEST_H_