notes: 2.3.0 -> 2.3.1 (#352950)
[NixPkgs.git] / nixos / tests / terminal-emulators.nix
blob9195f619c8d21293056cb55e1a16f03eed432432
1 # Terminal emulators all present a pretty similar interface.
2 # That gives us an opportunity to easily test their basic functionality with a single codebase.
4 # There are two tests run on each terminal emulator
5 # - can it successfully execute a command passed on the cmdline?
6 # - can it successfully display a colour?
7 # the latter is used as a proxy for "can it display text?", without going through all the intricacies of OCR.
9 # 256-colour terminal mode is used to display the test colour, since it has a universally-applicable palette (unlike 8- and 16- colour, where the colours are implementation-defined), and it is widely supported (unlike 24-bit colour).
11 # Future work:
12 # - Wayland support (both for testing the existing terminals, and for testing wayland-only terminals like foot and havoc)
13 # - Test keyboard input? (skipped for now, to eliminate the possibility of race conditions and focus issues)
15 { system ? builtins.currentSystem,
16   config ? {},
17   pkgs ? import ../.. { inherit system config; }
20 with import ../lib/testing-python.nix { inherit system pkgs; };
21 with pkgs.lib;
23 let tests = {
24       alacritty.pkg = p: p.alacritty;
26       contour.pkg = p: p.contour;
27       contour.cmd = "contour early-exit-threshold 0 execute $command";
29       cool-retro-term.pkg = p: p.cool-retro-term;
30       cool-retro-term.colourTest = false; # broken by gloss effect
32       ctx.pkg = p: p.ctx;
33       ctx.pinkValue = "#FE0065";
35       darktile.pkg = p: p.darktile;
37       deepin-terminal.pkg = p: p.deepin.deepin-terminal;
39       eterm.pkg = p: p.eterm;
40       eterm.executable = "Eterm";
41       eterm.pinkValue = "#D40055";
43       germinal.pkg = p: p.germinal;
45       gnome-terminal.pkg = p: p.gnome-terminal;
47       guake.pkg = p: p.guake;
48       guake.cmd = "SHELL=$command guake --show";
49       guake.kill = true;
51       hyper.pkg = p: p.hyper;
53       kermit.pkg = p: p.kermit-terminal;
55       kgx.pkg = p: p.kgx;
56       kgx.cmd = "kgx -e $command";
57       kgx.kill = true;
59       kitty.pkg = p: p.kitty;
60       kitty.cmd = "kitty $command";
62       konsole.pkg = p: p.plasma5Packages.konsole;
64       lomiri-terminal-app.pkg = p: p.lomiri.lomiri-terminal-app;
65       # after recent Mesa change, borked software rendering config under x86_64 icewm?
66       # BGR colour display on x86_64, RGB on aarch64
67       lomiri-terminal-app.colourTest = false;
69       lxterminal.pkg = p: p.lxterminal;
71       mate-terminal.pkg = p: p.mate.mate-terminal;
72       mate-terminal.cmd = "SHELL=$command mate-terminal --disable-factory"; # factory mode uses dbus, and we don't have a proper dbus session set up
74       mlterm.pkg = p: p.mlterm;
76       mrxvt.pkg = p: p.mrxvt;
78       qterminal.pkg = p: p.lxqt.qterminal;
79       qterminal.kill = true;
81       rio.pkg = p: p.rio;
82       rio.cmd = "rio -e $command";
83       rio.colourTest = false; # the rendering is changing too much so colors change every release.
85       roxterm.pkg = p: p.roxterm;
86       roxterm.cmd = "roxterm -e $command";
88       sakura.pkg = p: p.sakura;
90       st.pkg = p: p.st;
91       st.kill = true;
93       stupidterm.pkg = p: p.stupidterm;
94       stupidterm.cmd = "stupidterm -- $command";
96       terminator.pkg = p: p.terminator;
97       terminator.cmd = "terminator -e $command";
99       terminology.pkg = p: p.enlightenment.terminology;
100       terminology.cmd = "SHELL=$command terminology --no-wizard=true";
101       terminology.colourTest = false; # broken by gloss effect
103       termite.pkg = p: p.termite;
105       termonad.pkg = p: p.termonad;
107       tilda.pkg = p: p.tilda;
109       tilix.pkg = p: p.tilix;
110       tilix.cmd = "tilix -e $command";
112       urxvt.pkg = p: p.rxvt-unicode;
114       wayst.pkg = p: p.wayst;
115       wayst.pinkValue = "#FF0066";
117       # times out after spending many hours
118       #wezterm.pkg = p: p.wezterm;
120       xfce4-terminal.pkg = p: p.xfce.xfce4-terminal;
122       xterm.pkg = p: p.xterm;
124       zutty.pkg = p: p.zutty;
125     };
126 in mapAttrs (name: { pkg, executable ? name, cmd ? "SHELL=$command ${executable}", colourTest ? true, pinkValue ? "#FF0087", kill ? false }: makeTest
128   name = "terminal-emulator-${name}";
129   meta = with pkgs.lib.maintainers; {
130     maintainers = [ jjjollyjim ];
131   };
133   nodes.machine = { pkgsInner, ... }:
135   {
136     imports = [ ./common/x11.nix ./common/user-account.nix ];
138     # Hyper (and any other electron-based terminals) won't run as root
139     test-support.displayManager.auto.user = "alice";
141     environment.systemPackages = [
142       (pkg pkgs)
143       (pkgs.writeShellScriptBin "report-success" ''
144         echo 1 > /tmp/term-ran-successfully
145         ${optionalString kill "pkill ${executable}"}
146       '')
147       (pkgs.writeShellScriptBin "display-colour" ''
148         # A 256-colour background colour code for pink, then spaces.
149         #
150         # Background is used rather than foreground to minimize the effect of anti-aliasing.
151         #
152         # Keep adding more in case the window is partially offscreen to the left or requires
153         # a change to correctly redraw after initialising the window (as with ctx).
155         while :
156         do
157             echo -ne "\e[48;5;198m                   "
158             sleep 0.5
159         done
160         sleep infinity
161       '')
162       (pkgs.writeShellScriptBin "run-in-this-term" "sudo -u alice run-in-this-term-wrapped $1")
164       (pkgs.writeShellScriptBin "run-in-this-term-wrapped" "command=\"$(which \"$1\")\"; ${cmd}")
165     ];
167     # Helpful reminder to add this test to passthru.tests
168     warnings = if !((pkg pkgs) ? "passthru" && (pkg pkgs).passthru ? "tests") then [ "The package for ${name} doesn't have a passthru.tests" ] else [ ];
169   };
171   # We need imagemagick, though not tesseract
172   enableOCR = true;
174   testScript = { nodes, ... }: let
175   in ''
176     with subtest("wait for x"):
177         start_all()
178         machine.wait_for_x()
180     with subtest("have the terminal run a command"):
181         # We run this command synchronously, so we can be certain the exit codes are happy
182         machine.${if kill then "execute" else "succeed"}("run-in-this-term report-success")
183         machine.wait_for_file("/tmp/term-ran-successfully")
184     ${optionalString colourTest ''
186     import tempfile
187     import subprocess
190     def check_for_pink(final=False) -> bool:
191         with tempfile.NamedTemporaryFile() as tmpin:
192             machine.send_monitor_command("screendump {}".format(tmpin.name))
194             cmd = 'convert {} -define histogram:unique-colors=true -format "%c" histogram:info:'.format(
195                 tmpin.name
196             )
197             ret = subprocess.run(cmd, shell=True, capture_output=True)
198             if ret.returncode != 0:
199                 raise Exception(
200                     "image analysis failed with exit code {}".format(ret.returncode)
201                 )
203             text = ret.stdout.decode("utf-8")
204             return "${pinkValue}" in text
207     with subtest("ensuring no pink is present without the terminal"):
208         assert (
209             check_for_pink() == False
210         ), "Pink was present on the screen before we even launched a terminal!"
212     with subtest("have the terminal display a colour"):
213         # We run this command in the background
214         assert machine.shell is not None
215         machine.shell.send(b"(run-in-this-term display-colour |& systemd-cat -t terminal) &\n")
217         with machine.nested("Waiting for the screen to have pink on it:"):
218             retry(check_for_pink)
219   ''}'';
222   ) tests