nix: add graphical-gnome-test

This VM integration test spawns Gnome, monado-service,
stardust-xr-server, flatland and weston-cliptest and tests that the
functionality works correctly. The result is a screenshot. If any
program in the test produces an exit code above 0 it will fail the test,
graphical rendering bugs should be visible in the resulting screenshot
This commit is contained in:
matthewcroughan
2023-05-11 15:43:41 +01:00
committed by Matthew Croughan
parent 1740d55f9c
commit 13da4c8d60
3 changed files with 190 additions and 2 deletions

View File

@@ -20,3 +20,26 @@ cargo build
```bash
cargo install
```
## Test
##### Gnome Graphical Integration Test
- `nix build .#gnome-graphical-test`
This test uses Nix to reproducibly execute a QEMU virtual machine which
spawns a full Gnome desktop. It runs `monado-service`, `stardust-xr-server`
`flatland` underneath of Gnome and then attaches `weston-cliptest` to the
`flatland` process running underneath of `stardust-xr-server`, the result is
a screenshot in PNG format that should look like expected. If any process in
this test produces an exit code above 0, the test will fail, graphical bugs
should be visible in the screenshot. An example of the result is below.
###### Result
![image](https://github.com/StardustXR/server/assets/26458780/e21cd039-2528-4568-b20a-ce4abfab6d9b)
##### Everything
`nix flake check` will build every test underneath of the `checks` attribute in the `flake.nix`

View File

@@ -2,10 +2,14 @@
# 22.11 does not include PR #218472, hence we use the unstable version
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
# Since we do not have a monorepo, we have to fetch Flatland in order to use
# it to create VM Tests
inputs.flatland.url = "github:StardustXR/flatland";
inputs.fenix.url = github:nix-community/fenix;
inputs.fenix.inputs.nixpkgs.follows = "nixpkgs";
outputs = { self, nixpkgs, fenix }:
outputs = { self, nixpkgs, fenix, ... }:
let
name = "server";
pkgs = system: import nixpkgs {
@@ -82,6 +86,12 @@
packages."x86_64-linux".default = package (pkgs "x86_64-linux");
packages."aarch64-linux".default = package (pkgs "aarch64-linux");
packages."x86_64-linux".gnome-graphical-test = self.checks.x86_64-linux.gnome-graphical-test;
packages."aarch64-linux".gnome-graphical-test = self.checks.aarch64-linux.gnome-graphical-test;
checks."x86_64-linux".gnome-graphical-test = (pkgs "x86_64-linux").nixosTest (import ./nix/gnome-graphical-test.nix { pkgs = (pkgs "x86_64-linux"); inherit self; });
checks."aarch64-linux".gnome-graphical-test = (pkgs "aarch64-linux").nixosTest (import ./nix/gnome-graphical-test.nix { pkgs = (pkgs "aarch64-linux"); inherit self; });
devShells."x86_64-linux".default = shell (pkgs "x86_64-linux");
devShells."aarch64-linux".default = shell (pkgs "aarch64-linux");
};

View File

@@ -0,0 +1,155 @@
{ pkgs, lib ? pkgs.lib, self, ... }:
# Some code is copy-pasted from https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/gnome.nix
# TODO: make this less boiler-platey and make a function like mkGnomeTest that does all this and upstream it to nixpkgs
{
name = "stardust-xr-server-gnome-vmtest";
meta = with lib; {
maintainers = [ maintainers.matthewcroughan ];
};
nodes.machine = { ... }: {
imports = [ "${pkgs.path}/nixos/tests/common/user-account.nix" ];
virtualisation.qemu.options = [
"-device virtio-gpu-pci"
];
environment.systemPackages = [ pkgs.monado ];
services.xserver = {
enable = true;
desktopManager.gnome = {
enable = true;
debug = true;
# Set a nice desktop background that is pleasing to the eyes :3
extraGSettingsOverrides = ''
[org.gnome.desktop.background]
picture-uri='file://${pkgs.gnome.gnome-backgrounds}/share/backgrounds/gnome/blobs-l.svg'
picture-uri-dark='file://${pkgs.gnome.gnome-backgrounds}/share/backgrounds/gnome/blobs-l.svg'
'';
};
displayManager = {
gdm = {
enable = true;
debug = true;
};
autoLogin = {
enable = true;
user = "alice";
};
};
};
systemd.user.services = {
"monado" = {
after = [ "graphical-session.target" "default.target" "org.gnome.Shell@wayland.service" ];
environment = {
XRT_COMPOSITOR_FORCE_WAYLAND = "1";
WAYLAND_DISPLAY = "wayland-0";
};
serviceConfig = {
ExecStartPre = [
"${pkgs.writeShellScript "sleep" ''
sleep 3
''}"
];
ExecStart = let
# stdin disappears in NixOS test driver ( machine.succeed() ), requiring us to specify < /dev/ttyS0 to fake stdin
exec-monado-service = pkgs.writeShellScript "exec-monado-service" "${pkgs.monado}/bin/monado-service < /dev/ttyS0";
in [
"${exec-monado-service}"
];
};
};
"stardust-xr-server" = {
after = [ "monado.service" ];
serviceConfig = {
Type = "notify";
NotifyAccess = "all";
ExecStartPre = [
"${pkgs.writeShellScript "sleep" ''
sleep 3
''}"
];
ExecStart = let
notifyReady = pkgs.writeShellScript "notifyReady" "systemd-notify --ready";
exec-stardust-xr-server = pkgs.writeShellScript "exec-stardust-xr-server" "${self.packages.${pkgs.hostPlatform.system}.default}/bin/stardust-xr-server -e ${notifyReady}";
in [
"${exec-stardust-xr-server}"
];
};
};
"weston-cliptest" = {
after = [ "flatland.service" ];
environment.WAYLAND_DISPLAY = "wayland-1";
serviceConfig = {
ExecStart = [
"${pkgs.weston}/bin/weston-cliptest"
];
};
};
"flatland" = {
after = [ "stardust-xr-server.service" ];
serviceConfig = {
ExecStart = [
"${self.inputs.flatland.packages.${pkgs.hostPlatform.system}.default}/bin/flatland"
];
};
};
"org.gnome.Shell@wayland" = {
wants = [ "monado.service" "stardust-xr-server.service" "flatland.service" "weston-cliptest.service" ];
serviceConfig = {
ExecStart = [
# Clear the list before overriding it.
""
# Eval API is now internal so Shell needs to run in unsafe mode.
# TODO: improve test driver so that it supports openqa-like manipulation
# that would allow us to drop this mess.
"${pkgs.gnome.gnome-shell}/bin/gnome-shell --unsafe-mode"
];
};
};
};
};
testScript = { nodes, ... }: let
# Keep line widths somewhat managable
user = nodes.machine.config.users.users.alice;
uid = toString user.uid;
bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus";
gdbus = "${bus} gdbus";
su = command: "su ${user.name} -c '${command}'";
# Call javascript in gnome shell, returns a tuple (success, output), where
# `success` is true if the dbus call was successful and output is what the
# javascript evaluates to.
eval = "call --session -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval";
# False when startup is done
startingUp = su "${gdbus} ${eval} Main.layoutManager._startingUp";
in ''
with subtest("Login to GNOME with GDM"):
# wait for gdm to start
machine.wait_for_unit("display-manager.service")
# wait for the wayland server
machine.wait_for_file("/run/user/${uid}/wayland-0")
# wait for alice to be logged in
machine.wait_for_unit("default.target", "${user.name}")
# check that logging in has given the user ownership of devices
assert "alice" in machine.succeed("getfacl -p /dev/snd/timer")
with subtest("Wait for GNOME Shell"):
# correct output should be (true, 'false')
machine.wait_until_succeeds(
"${startingUp} | grep -q 'true,..false'"
)
# To allow monado-service to use < /dev/ttyS0
machine.succeed("chown alice /dev/ttyS0")
with subtest("Open Monado and StardustXR"):
# Close the Activities view so that Shell can correctly track the focused window.
machine.send_key("esc")
machine.wait_for_unit("monado.service", "${user.name}")
machine.wait_for_unit("stardust-xr-server.service", "${user.name}")
machine.wait_for_unit("flatland.service", "${user.name}")
machine.wait_for_unit("weston-cliptest.service", "${user.name}")
machine.sleep(3)
machine.screenshot("screen")
'';
}