summary refs log tree commit diff
path: root/release/checks
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-03-12 13:36:15 +0000
committerAlyssa Ross <hi@alyssa.is>2023-07-28 19:12:14 +0000
commitf76b542bf129def2dbca7c99ef1cc2ec6386dd2f (patch)
tree1050b9dd17f31505db24902097ae368f0a48589d /release/checks
parent2b1ee70d3e3c2c048ca6e8d4df8818399925b6cb (diff)
downloadspectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.tar
spectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.tar.gz
spectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.tar.bz2
spectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.tar.lz
spectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.tar.xz
spectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.tar.zst
spectrum-f76b542bf129def2dbca7c99ef1cc2ec6386dd2f.zip
release/checks/wayland: init
This is a smoke test for crosvm vhost-user-gpu.  It starts Weston and
the img/app VM in crosvm, and checks that the hello-wayland window
from the VM appears, using a small Weston plugin.

Hopefully this will make it easier to keep up with upstream crosvm,
because testing crosvm versions can be automated.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
Diffstat (limited to 'release/checks')
-rw-r--r--release/checks/default.nix2
-rw-r--r--release/checks/wayland/default.nix70
-rw-r--r--release/checks/wayland/surface-notify/default.nix19
-rw-r--r--release/checks/wayland/surface-notify/meson.build13
-rw-r--r--release/checks/wayland/surface-notify/module.c79
-rw-r--r--release/checks/wayland/surface-notify/shell.nix9
6 files changed, 192 insertions, 0 deletions
diff --git a/release/checks/default.nix b/release/checks/default.nix
index e06d292..bb871ec 100644
--- a/release/checks/default.nix
+++ b/release/checks/default.nix
@@ -21,4 +21,6 @@ import ../../lib/eval-config.nix ({ ... } @ args:
   shellcheck = import ./shellcheck.nix args;
 
   try = import ./try.nix args;
+
+  wayland = import ./wayland args;
 })
diff --git a/release/checks/wayland/default.nix b/release/checks/wayland/default.nix
new file mode 100644
index 0000000..9c18d18
--- /dev/null
+++ b/release/checks/wayland/default.nix
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2023 Alyssa Ross <hi@alyssa.is>
+
+import ../../../lib/eval-config.nix ({ config, ... }:
+
+let
+  inherit (import ../../../host/rootfs { inherit config; }) appvm;
+  run = import ../../../vm/app/hello-wayland.nix { inherit config; };
+  surface-notify = import ./surface-notify { inherit config; };
+in
+
+config.pkgs.nixosTest ({ pkgs, ... }: {
+  name = "spectrum-wayland";
+
+  nodes.machine = { ... }: {
+    hardware.opengl.enable = true;
+
+    systemd.services.crosvm = {
+      after = [ "crosvm-gpu.service" "weston.service" ];
+      requires = [ "crosvm-gpu.service" "weston.service" ];
+      serviceConfig.ExecStart = "${pkgs.crosvm}/bin/crosvm run --disk ${appvm}/img/appvm/blk/root.img --disk ${run}/blk/run.img -p \"console=ttyS0 root=PARTLABEL=root\" --vhost-user-gpu /run/crosvm-gpu.sock --serial type=stdout,hardware=virtio-console,stdin=true ${appvm}/img/appvm/vmlinux";
+    };
+
+    systemd.services.crosvm-gpu = {
+      requires = [ "weston.service" ];
+      script = ''
+        rm -f /run/crosvm-gpu.sock
+        (
+            while ! [ -S /run/crosvm-gpu.sock ]; do
+                sleep .1
+            done
+            systemd-notify --ready --no-block
+        ) &
+        exec ${pkgs.crosvm}/bin/crosvm device gpu \
+            --socket /run/crosvm-gpu.sock \
+            --wayland-sock /run/wayland-1 \
+            --params '{"context-types":"cross-domain"}'
+      '';
+      serviceConfig.NotifyAccess = "all";
+      serviceConfig.Type = "notify";
+    };
+
+    systemd.services.surface-notify-socket = {
+      serviceConfig.ExecStart = "${pkgs.coreutils}/bin/mkfifo /run/surface-notify";
+      serviceConfig.RemainAfterExit = true;
+      serviceConfig.Type = "oneshot";
+    };
+
+    systemd.services.weston = {
+      after = [ "surface-notify-socket.service" ];
+      requires = [ "surface-notify-socket.service" ];
+      environment.XDG_RUNTIME_DIR = "/run";
+      environment.WAYLAND_DEBUG = "server";
+      serviceConfig.ExecStart = "${pkgs.westonLite}/bin/weston --modules ${surface-notify}/lib/weston/surface-notify.so,systemd-notify.so";
+      serviceConfig.TTYPath = "/dev/tty7";
+      serviceConfig.Type = "notify";
+    };
+  };
+
+  testScript = { ... }: ''
+    machine.wait_for_unit('multi-user.target')
+
+    machine.start_job('crosvm.service')
+
+    machine.wait_for_unit('surface-notify-socket.service');
+    machine.succeed('test "$(wc -c /run/surface-notify)" = "1 /run/surface-notify"', timeout=180)
+
+    machine.screenshot('weston')
+  '';
+}))
diff --git a/release/checks/wayland/surface-notify/default.nix b/release/checks/wayland/surface-notify/default.nix
new file mode 100644
index 0000000..1c8171f
--- /dev/null
+++ b/release/checks/wayland/surface-notify/default.nix
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2023 Alyssa Ross <hi@alyssa.is>
+
+import ../../../../lib/eval-config.nix ({ config, src, ... }: config.pkgs.callPackage (
+
+{ lib, stdenv, meson, ninja, pkg-config
+, libxkbcommon, pixman, wayland, westonLite
+}:
+
+stdenv.mkDerivation {
+  name = "surface-notify";
+
+  inherit src;
+  sourceRoot = "source/release/checks/wayland/surface-notify";
+
+  nativeBuildInputs = [ meson ninja pkg-config ];
+  buildInputs = [ libxkbcommon pixman wayland westonLite ];
+}
+) { })
diff --git a/release/checks/wayland/surface-notify/meson.build b/release/checks/wayland/surface-notify/meson.build
new file mode 100644
index 0000000..624eef1
--- /dev/null
+++ b/release/checks/wayland/surface-notify/meson.build
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: EUPL-1.2+
+# SPDX-FileCopyrightText: 2023 Alyssa Ross <hi@alyssa.is>
+
+project('surface-notify', 'c', default_options : [ 'warning_level=2' ])
+
+libweston = dependency('libweston-12')
+wayland_server = dependency('wayland-server')
+
+shared_library('surface-notify', 'module.c',
+  name_prefix : '',
+  dependencies : [ libweston, wayland_server ],
+  install : true,
+  install_dir : get_option('libdir') / 'weston')
diff --git a/release/checks/wayland/surface-notify/module.c b/release/checks/wayland/surface-notify/module.c
new file mode 100644
index 0000000..e6688a2
--- /dev/null
+++ b/release/checks/wayland/surface-notify/module.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: EUPL-1.2+
+// SPDX-FileCopyrightText: 2023 Alyssa Ross <hi@alyssa.is>
+
+// A Weston module that sends a notification into a fifo when a
+// hello-wayland window appears.
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <libweston/libweston.h>
+#include <libweston/zalloc.h>
+
+static void on_commit(struct wl_listener *, struct weston_surface *surface)
+{
+	int fd;
+	int32_t width, height;
+
+	// Use the size of the surface as a heuristic for identifying
+	// hello-wayland.  If we had security contexts[1], we could be
+	// more precise about this.
+	//
+	// [1]: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/68
+	weston_surface_get_content_size(surface, &width, &height);
+	if (!surface->output || width != 128 || height != 128)
+		return;
+
+	if ((fd = open("/run/surface-notify", O_WRONLY)) == -1) {
+		weston_log("opening /run/surface-notify: %m\n");
+		return;
+	}
+
+	if (write(fd, "\n", 1) == -1)
+		weston_log("writing to /run/surface-notify: %m\n");
+
+	close(fd);
+}
+
+static void on_destroy(struct wl_listener *listener,
+		       struct weston_surface *surface)
+{
+	struct wl_listener *commit_listener = wl_signal_get(
+		&surface->commit_signal, (wl_notify_func_t)on_commit);
+
+	wl_list_remove(&commit_listener->link);
+	free(commit_listener);
+
+	wl_list_remove(&listener->link);
+	free(listener);
+}
+
+static void add_listener(struct wl_signal *signal, wl_notify_func_t notify)
+{
+	struct wl_listener *listener = zalloc(sizeof *listener);
+	if (!listener) {
+		weston_log("failed to allocate listener\n");
+		return;
+	}
+
+	listener->notify = notify;
+	wl_signal_add(signal, listener);
+}
+
+static void on_create(struct wl_listener *, struct weston_surface *surface)
+{
+	add_listener(&surface->commit_signal, (wl_notify_func_t)on_commit);
+	add_listener(&surface->destroy_signal, (wl_notify_func_t)on_destroy);
+}
+
+static struct wl_listener create_surface_listener = {
+	.notify = (wl_notify_func_t)on_create,
+};
+
+int wet_module_init(struct weston_compositor *compositor, int *, char *[])
+{
+	wl_signal_add(&compositor->create_surface_signal,
+		      &create_surface_listener);
+
+	return 0;
+}
diff --git a/release/checks/wayland/surface-notify/shell.nix b/release/checks/wayland/surface-notify/shell.nix
new file mode 100644
index 0000000..bc5ca3f
--- /dev/null
+++ b/release/checks/wayland/surface-notify/shell.nix
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2023 Alyssa Ross <hi@alyssa.is>
+
+{ ... } @ args:
+
+(import ./. args).overrideAttrs ({ hardeningDisable ? [], ... }: {
+  # Not compatible with Meson's default -O0.
+  hardeningDisable = hardeningDisable ++ [ "fortify" ];
+}))