Skip to content

Latest commit

 

History

History
132 lines (97 loc) · 5.09 KB

TESTING.md

File metadata and controls

132 lines (97 loc) · 5.09 KB

Writing Sommelier tests

Sommelier's main function is passing messages between other applications.

  • For peer Wayland instances, that's the host compositor on one hand, and a Wayland client on the other.
  • X11 instances are similar, except the Wayland client is Xwayland. Sommelier also connects to Xwayland using the X11 protocol, in Sommelier's role as the X Window Manager.

Most test cases can be implemented by faking input over one of three connections, and asserting that Sommelier produces appropriate output over another connection. The following sections describe how.

For tests applicable to peer Wayland instances, your test fixture should inherit from WaylandTestBase. For X11 instances, inherit from X11TestBase.

Host compositor -> Sommelier (Wayland events)

Wayland events are received on Wayland client objects, so first you need to create one. The specifics will vary depending on the protocol, but generally you'll want to first obtain a global, and possibly request another object from it.

As we don't have a real Wayland server, WaylandTestBase::Connect() advertises globals instead. For example, xdg_wm_base is advertised as follows:

sl_registry_handler(..., "xdg_wm_base",
    XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION);

If the global you need isn't there, feel free to add it.

Once the "server" advertises the global, find it in ctx and use Wayland requests as normal to create other client objects. For example, to create a wl_surface, call wl_compositor_create_surface(ctx.compositor->internal).

The canonical way to fake receiving a Wayland event from the host compositor is to simply call the event handler directly, using the following pattern:

HostEventHandler(proxy)->eventname(nullptr, params...);

Where proxy is any Wayland client object such as a wl_surface, eventname is the event your test pretends to receive, and the parameters vary depending on the Wayland event.

If you get template-related errors when using HostEventHandler, fix them by adding a MAP_STRUCT_TO_LISTENER() mapping for the Wayland client object's type, following existing examples.

Sommelier -> host compositor (Wayland requests)

The Sommelier build generates C++ "shim" classes for each Wayland client object, which simply wrap libwayland's generated functions. For example, XdgSurfaceShim::set_window_geometry calls xdg_surface_set_window_geometry. We are moving towards using these shim classes throughout Sommelier instead of calling libwayland directly. This lets us use gMock to replace those shims in tests, and verify that the expected Wayland request was sent.

The mock classes are also created by codegen. The test must simply install them, overriding the real implementation:

// In fixture class declaration:
NiceMock<MockXdgSurfaceShim> mock_xdg_surface_shim_;
...
// In SetUp():
set_xdg_surface_shim(&mock_xdg_surface_shim_);

Then verify each request using standard gMock syntax:

EXPECT_CALL(mock_xdg_surface_shim_, set_window_geometry(<arguments go here>))
    .Times(1);

Wayland client -> Sommelier (Wayland requests)

For X11 instances, the Wayland client is Xwayland.

Create an instance of FakeWaylandClient. This creates an actual Wayland client and connects it to Sommelier, such that it can send Wayland requests as per usual, and Sommelier will handle them as if they'd been sent by a real client.

FakeWaylandClient exposes methods to have the client perform various tasks, which are then driven by the test case. See FakeWaylandClient::CreateSurface() for an example. Feel free to add more as your test case requires. If the new method is very specific to your test case, consider subclassing FakeWaylandClient.

  • When creating a new method, remember to call wl_display_flush() so that Sommelier actually receives the sent request.
  • X11TestBase already creates a FakeWaylandClient representing Xwayland. See X11TestBase::xwayland.

Sommelier -> Wayland client (Wayland events)

For X11 instances, the Wayland client is Xwayland.

Same as "Sommelier -> host compositor" above, but the method to verify will begin with send_. For example, to verify that Sommelier sends xdg_surface.configure() to the client, write:

EXPECT_CALL(mock_xdg_surface_shim_, send_configure(<arguments go here>))
    .Times(1);

Sommelier -> Xwayland (X11 requests)

The XcbShim class wraps libxcb functions. We're moving towards calling all xcb functions through this shim. X11TestBase creates a MockXcbShim which can be used to verify these calls.

For example, to verify that Sommelier sends a ConfigureWindow request, write:

EXPECT_CALL(xcb, configure_window(<arguments go here>))
    .Times(1);

Xwayland -> Sommelier (X11 events)

For now, to fake receiving an X11 event, simply call the corresponding handler function directly. For example, sl_handle_client_message() or sl_handle_map_request(). We might make this nicer in future by exposing a single function to handle all X11 events.