blob: 168714df6aa2a6c33c88fad7c0310cf8ac5a52ac [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef VM_TOOLS_SOMMELIER_TESTING_X11_TEST_BASE_H_
#define VM_TOOLS_SOMMELIER_TESTING_X11_TEST_BASE_H_
#include <xcb/xproto.h>
#include <memory>
#include <string>
#include "../xcb/mock-xcb-shim.h"
#include "mock-viewporter-shim.h" // NOLINT(build/include_directory)
#include "wayland-test-base.h" // NOLINT(build/include_directory)
namespace vm_tools {
namespace sommelier {
// Fixture for unit tests which exercise both Wayland and X11 functionality.
class X11TestBase : public WaylandTestBase {
public:
void InitContext() override {
WaylandTestBase::InitContext();
ctx.xwayland = 1;
// Always delegate ID generation to the fake XCB shim, even for test cases
// that never use the fake for anything else. This prevents ID collisions.
xcb.DelegateIdGenerationToFake();
// Create a fake screen with somewhat plausible values.
// Some of these are not realistic because they refer to things not present
// in the mocked X environment (such as specifying a root window with ID 0).
ctx.screen = static_cast<xcb_screen_t*>(malloc(sizeof(xcb_screen_t)));
ctx.screen->root = 0x0;
ctx.screen->default_colormap = 0x0;
ctx.screen->white_pixel = 0x00ffffff;
ctx.screen->black_pixel = 0x00000000;
ctx.screen->current_input_masks = 0x005a0000;
ctx.screen->width_in_pixels = 1920;
ctx.screen->height_in_pixels = 1080;
ctx.screen->width_in_millimeters = 508;
ctx.screen->height_in_millimeters = 285;
ctx.screen->min_installed_maps = 1;
ctx.screen->max_installed_maps = 1;
ctx.screen->root_visual = 0x0;
ctx.screen->backing_stores = 0x01;
ctx.screen->save_unders = 0;
ctx.screen->root_depth = 24;
ctx.screen->allowed_depths_len = 0;
}
void Connect() override {
set_xcb_shim(&xcb);
set_wp_viewport_shim(&mock_viewport_shim_);
WaylandTestBase::Connect();
// Pretend Xwayland has connected to Sommelier as a Wayland client.
xwayland = std::make_unique<FakeWaylandClient>(&ctx);
ctx.client = xwayland->client;
// TODO(cpelling): mock out more of xcb so this isn't needed
ctx.connection = xcb_connect(nullptr, nullptr);
}
~X11TestBase() override { set_xcb_shim(nullptr); }
virtual sl_window* CreateWindowWithoutRole() {
xcb_window_t window_id = xcb.generate_id(ctx.connection);
sl_create_window(&ctx, window_id, 0, 0, 800, 600, 0);
sl_window* window = sl_lookup_window(&ctx, window_id);
EXPECT_NE(window, nullptr);
return window;
}
virtual sl_window* CreateToplevelWindow() {
sl_window* window = CreateWindowWithoutRole();
// Pretend we created a frame window too
window->frame_id = xcb.generate_id(ctx.connection);
window->host_surface_id = SurfaceId(xwayland->CreateSurface());
sl_window_update(window);
Pump();
// Default to the first output if any exist.
if (!ctx.host_outputs.empty()) {
struct sl_host_output* output = nullptr;
output = ctx.host_outputs[0];
HostEventHandler(window->paired_surface->proxy)
->enter(nullptr, window->paired_surface->proxy, output->proxy);
}
Pump();
return window;
}
std::string StringPropertyForTesting(xcb_window_t window_id,
xcb_atom_t property_name) {
xcb_get_property_cookie_t cookie = xcb.get_property(
nullptr, 0, window_id, property_name, XCB_ATOM_STRING, 0, 1024);
xcb_get_property_reply_t* reply =
xcb.get_property_reply(nullptr, cookie, nullptr);
EXPECT_TRUE(reply) << "get_property_reply() returned null. Try calling "
"xcb.DelegateToFake().";
std::string result;
if (reply->format != 8) {
result = "error: expected X11 property format 8, got " +
std::to_string(reply->format);
} else if (reply->type != XCB_ATOM_STRING) {
result = "error: expected X11 property type XCB_ATOM_STRING";
} else {
void* value = xcb.get_property_value(reply);
result = std::string(static_cast<char*>(value), reply->length);
free(value);
}
free(reply);
return result;
}
protected:
NiceMock<MockXcbShim> xcb;
std::unique_ptr<FakeWaylandClient> xwayland;
NiceMock<MockWpViewportShim> mock_viewport_shim_;
};
// Fixture for unit tests which use direct scale.
class X11DirectScaleTest : public X11TestBase {
public:
void InitContext() override {
X11TestBase::InitContext();
ctx.use_direct_scale = true;
}
void Connect() override {
X11TestBase::Connect();
wl_registry* registry = wl_display_get_registry(ctx.display);
sl_registry_handler(&ctx, registry, next_server_id++,
"zxdg_output_manager_v1",
WP_VIEWPORTER_DESTROY_SINCE_VERSION);
}
};
} // namespace sommelier
} // namespace vm_tools
#endif // VM_TOOLS_SOMMELIER_TESTING_X11_TEST_BASE_H_