1{
2 config,
3 lib,
4 testName,
5 enableAutologin,
6 enableXWayland,
7 ...
8}:
9
10{
11 name = testName;
12
13 meta.maintainers = lib.teams.cosmic.members;
14
15 nodes.machine = {
16 imports = [ ./common/user-account.nix ];
17
18 services = {
19 # For `cosmic-store` to be added to `environment.systemPackages`
20 # and for it to work correctly because Flatpak is a runtime
21 # dependency of `cosmic-store`.
22 flatpak.enable = true;
23
24 displayManager.cosmic-greeter.enable = true;
25 desktopManager.cosmic = {
26 enable = true;
27 xwayland.enable = enableXWayland;
28 };
29 };
30
31 services.displayManager.autoLogin = lib.mkIf enableAutologin {
32 enable = true;
33 user = "alice";
34 };
35
36 environment.systemPackages = with config.node.pkgs; [
37 # These two packages are used to check if a window was opened
38 # under the COSMIC session or not. Kinda important.
39 # TODO: Move the check from the test module to
40 # `nixos/lib/test-driver/src/test_driver/machine.py` so more
41 # Wayland-only testing can be done using the existing testing
42 # infrastructure.
43 jq
44 lswt
45 ];
46
47 # So far, all COSMIC tests launch a few GUI applications. In doing
48 # so, the default allocated memory to the guest of 1024M quickly
49 # poses a very high risk of an OOM-shutdown which is worse than an
50 # OOM-kill. Because now, the test failed, but not for a genuine
51 # reason, but an OOM-shutdown. That's an inconclusive failure
52 # which might possibly mask an actual failure. Not enabling
53 # systemd-oomd because we need said applications running for a
54 # few seconds. So instead, bump the allocated memory to the guest
55 # from 1024M to 4x; 4096M.
56 virtualisation.memorySize = 4096;
57 };
58
59 testScript =
60 { nodes, ... }:
61 let
62 cfg = nodes.machine;
63 user = cfg.users.users.alice;
64 DISPLAY = lib.strings.optionalString enableXWayland (
65 if enableAutologin then "DISPLAY=:0" else "DISPLAY=:1"
66 );
67 in
68 ''
69 #testName: ${testName}
70 ''
71 + (
72 if (enableAutologin) then
73 ''
74 with subtest("cosmic-greeter initialisation"):
75 machine.wait_for_unit("graphical.target", timeout=120)
76 ''
77 else
78 ''
79 from time import sleep
80
81 machine.wait_for_unit("graphical.target", timeout=120)
82 machine.wait_until_succeeds("pgrep --uid ${toString cfg.users.users.cosmic-greeter.name} --full cosmic-greeter", timeout=30)
83 # Sleep for 10 seconds for ensuring that `greetd` loads the
84 # password prompt for the login screen properly.
85 sleep(10)
86
87 with subtest("cosmic-session login"):
88 machine.send_chars("${user.password}\n", delay=0.2)
89 ''
90 )
91 + ''
92 # _One_ of the final processes to start as part of the
93 # `cosmic-session` target is the Workspaces applet. So, wait
94 # for it to start. The process existing means that COSMIC
95 # now handles any opened windows from now on.
96 machine.wait_until_succeeds("pgrep --uid ${toString user.uid} --full 'cosmic-panel-button com.system76.CosmicWorkspaces'", timeout=30)
97
98 # The best way to test for Wayland and XWayland is to launch
99 # the GUI applications and see the results yourself.
100 with subtest("Launch applications"):
101 # key: binary_name
102 # value: "app-id" as reported by `lswt`
103 gui_apps_to_launch = {}
104
105 # We want to ensure that the first-party applications
106 # start/launch properly.
107 gui_apps_to_launch['cosmic-edit'] = 'com.system76.CosmicEdit'
108 gui_apps_to_launch['cosmic-files'] = 'com.system76.CosmicFiles'
109 gui_apps_to_launch['cosmic-player'] = 'com.system76.CosmicPlayer'
110 gui_apps_to_launch['cosmic-settings'] = 'com.system76.CosmicSettings'
111 gui_apps_to_launch['cosmic-store'] = 'com.system76.CosmicStore'
112 gui_apps_to_launch['cosmic-term'] = 'com.system76.CosmicTerm'
113
114 for gui_app, app_id in gui_apps_to_launch.items():
115 # Don't fail the test if binary is absent
116 if machine.execute(f"su - ${user.name} -c 'command -v {gui_app}'", timeout=5)[0] == 0:
117 machine.succeed(f"su - ${user.name} -c 'WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/${toString user.uid} ${DISPLAY} {gui_app} >&2 &'", timeout=5)
118 # Nix builds the following non-commented expression to the following:
119 # `su - alice -c 'WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/1000 lswt --json | jq ".toplevels" | grep "^ \\"app-id\\": \\"{app_id}\\"$"' `
120 machine.wait_until_succeeds(f''''su - ${user.name} -c 'WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/${toString user.uid} lswt --json | jq ".toplevels" | grep "^ \\"app-id\\": \\"{app_id}\\"$"' '''', timeout=30)
121 machine.succeed(f"pkill {gui_app}", timeout=5)
122
123 machine.succeed("echo 'test completed succeessfully' > /${testName}", timeout=5)
124 machine.copy_from_vm('/${testName}')
125
126 machine.shutdown()
127 '';
128}