This repository was archived by the owner on Jan 30, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
vm_tools: sommelier: create TESTING.md
BUG=none TEST=n/a Change-Id: I217be0c86b368af708eeb54ed205966577ae59f2 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/4439649 Commit-Queue: Justin Huang <[email protected]> Tested-by: Chloe Pelling <[email protected]> Auto-Submit: Chloe Pelling <[email protected]> Reviewed-by: Justin Huang <[email protected]>
- Loading branch information
Showing
2 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# Writing Sommelier tests | ||
|
||
[Sommelier](README.md)'s main function is passing messages between other applications. | ||
|
||
* For [peer Wayland](README.md#peer-sommelier) instances, that's the host compositor on one hand, and a | ||
Wayland client on the other. | ||
* [X11 instances](README.md#x11-sommelier) 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()](https://crsrc.org/o/src/platform2/vm_tools/sommelier/testing/sommelier-test-util.h?q=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. |