···11+# Terminal emulators all present a pretty similar interface.22+# That gives us an opportunity to easily test their basic functionality with a single codebase.33+#44+# There are two tests run on each terminal emulator55+# - can it successfully execute a command passed on the cmdline?66+# - can it successfully display a colour?77+# the latter is used as a proxy for "can it display text?", without going through all the intricacies of OCR.88+#99+# 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).1010+#1111+# Future work:1212+# - Wayland support (both for testing the existing terminals, and for testing wayland-only terminals like foot and havoc)1313+# - Test keyboard input? (skipped for now, to eliminate the possibility of race conditions and focus issues)1414+1515+{ system ? builtins.currentSystem,1616+ config ? {},1717+ pkgs ? import ../.. { inherit system config; }1818+}:1919+2020+with import ../lib/testing-python.nix { inherit system pkgs; };2121+with pkgs.lib;2222+2323+let tests = {2424+ alacritty.pkg = p: p.alacritty;2525+2626+ contour.pkg = p: p.contour;2727+ contour.cmd = "contour $command";2828+2929+ cool-retro-term.pkg = p: p.cool-retro-term;3030+ cool-retro-term.colourTest = false; # broken by gloss effect3131+3232+ ctx.pkg = p: p.ctx;3333+ ctx.pinkValue = "#FE0065";3434+3535+ darktile.pkg = p: p.darktile;3636+3737+ eterm.pkg = p: p.eterm;3838+ eterm.executable = "Eterm";3939+ eterm.pinkValue = "#D40055";4040+4141+ germinal.pkg = p: p.germinal;4242+4343+ gnome-terminal.pkg = p: p.gnome.gnome-terminal;4444+4545+ guake.pkg = p: p.guake;4646+ guake.cmd = "SHELL=$command guake --show";4747+ guake.kill = true;4848+4949+ hyper.pkg = p: p.hyper;5050+5151+ kermit.pkg = p: p.kermit-terminal;5252+5353+ kgx.pkg = p: p.kgx;5454+ kgx.cmd = "kgx -e $command";5555+ kgx.kill = true;5656+5757+ kitty.pkg = p: p.kitty;5858+ kitty.cmd = "kitty $command";5959+6060+ konsole.pkg = p: p.plasma5Packages.konsole;6161+6262+ lxterminal.pkg = p: p.lxterminal;6363+6464+ mate-terminal.pkg = p: p.mate.mate-terminal;6565+ mate-terminal.cmd = "SHELL=$command mate-terminal --disable-factory"; # factory mode uses dbus, and we don't have a proper dbus session set up6666+6767+ mlterm.pkg = p: p.mlterm;6868+6969+ mrxvt.pkg = p: p.mrxvt;7070+7171+ qterminal.pkg = p: p.lxqt.qterminal;7272+ qterminal.kill = true;7373+7474+ roxterm.pkg = p: p.roxterm;7575+ roxterm.cmd = "roxterm -e $command";7676+7777+ sakura.pkg = p: p.sakura;7878+7979+ st.pkg = p: p.st;8080+ st.kill = true;8181+8282+ stupidterm.pkg = p: p.stupidterm;8383+ stupidterm.cmd = "stupidterm -- $command";8484+8585+ terminator.pkg = p: p.terminator;8686+ terminator.cmd = "terminator -e $command";8787+8888+ terminology.pkg = p: p.enlightenment.terminology;8989+ terminology.cmd = "SHELL=$command terminology --no-wizard=true";9090+ terminology.colourTest = false; # broken by gloss effect9191+9292+ termite.pkg = p: p.termite;9393+9494+ termonad.pkg = p: p.termonad;9595+9696+ tilda.pkg = p: p.tilda;9797+9898+ tilix.pkg = p: p.tilix;9999+ tilix.cmd = "tilix -e $command";100100+101101+ urxvt.pkg = p: p.rxvt-unicode;102102+103103+ wayst.pkg = p: p.wayst;104104+ wayst.pinkValue = "#FF0066";105105+106106+ wezterm.pkg = p: p.wezterm;107107+108108+ xfce4-terminal.pkg = p: p.xfce.xfce4-terminal;109109+110110+ xterm.pkg = p: p.xterm;111111+ };112112+in mapAttrs (name: { pkg, executable ? name, cmd ? "SHELL=$command ${executable}", colourTest ? true, pinkValue ? "#FF0087", kill ? false }: makeTest113113+{114114+ name = "terminal-emulator-${name}";115115+ meta = with pkgs.stdenv.lib.maintainers; {116116+ maintainers = [ jjjollyjim ];117117+ };118118+119119+ machine = { pkgsInner, ... }:120120+121121+ {122122+ imports = [ ./common/x11.nix ./common/user-account.nix ];123123+124124+ # Hyper (and any other electron-based terminals) won't run as root125125+ test-support.displayManager.auto.user = "alice";126126+127127+ environment.systemPackages = [128128+ (pkg pkgs)129129+ (pkgs.writeShellScriptBin "report-success" ''130130+ echo 1 > /tmp/term-ran-successfully131131+ ${optionalString kill "pkill ${executable}"}132132+ '')133133+ (pkgs.writeShellScriptBin "display-colour" ''134134+ # A 256-colour background colour code for pink, then spaces.135135+ #136136+ # Background is used rather than foreground to minimize the effect of anti-aliasing.137137+ #138138+ # Keep adding more in case the window is partially offscreen to the left or requires139139+ # a change to correctly redraw after initialising the window (as with ctx).140140+141141+ while :142142+ do143143+ echo -ne "\e[48;5;198m "144144+ sleep 0.5145145+ done146146+ sleep infinity147147+ '')148148+ (pkgs.writeShellScriptBin "run-in-this-term" "sudo -u alice run-in-this-term-wrapped $1")149149+150150+ (pkgs.writeShellScriptBin "run-in-this-term-wrapped" "command=\"$(which \"$1\")\"; ${cmd}")151151+ ];152152+153153+ # Helpful reminder to add this test to passthru.tests154154+ warnings = if !((pkg pkgs) ? "passthru" && (pkg pkgs).passthru ? "tests") then [ "The package for ${name} doesn't have a passthru.tests" ] else [ ];155155+ };156156+157157+ # We need imagemagick, though not tesseract158158+ enableOCR = true;159159+160160+ testScript = { nodes, ... }: let161161+ in ''162162+ with subtest("wait for x"):163163+ start_all()164164+ machine.wait_for_x()165165+166166+ with subtest("have the terminal run a command"):167167+ # We run this command synchronously, so we can be certain the exit codes are happy168168+ machine.${if kill then "execute" else "succeed"}("run-in-this-term report-success")169169+ machine.wait_for_file("/tmp/term-ran-successfully")170170+ ${optionalString colourTest ''171171+172172+ import tempfile173173+ import subprocess174174+175175+176176+ def check_for_pink(final=False) -> bool:177177+ with tempfile.NamedTemporaryFile() as tmpin:178178+ machine.send_monitor_command("screendump {}".format(tmpin.name))179179+180180+ cmd = 'convert {} -define histogram:unique-colors=true -format "%c" histogram:info:'.format(181181+ tmpin.name182182+ )183183+ ret = subprocess.run(cmd, shell=True, capture_output=True)184184+ if ret.returncode != 0:185185+ raise Exception(186186+ "image analysis failed with exit code {}".format(ret.returncode)187187+ )188188+189189+ text = ret.stdout.decode("utf-8")190190+ return "${pinkValue}" in text191191+192192+193193+ with subtest("ensuring no pink is present without the terminal"):194194+ assert (195195+ check_for_pink() == False196196+ ), "Pink was present on the screen before we even launched a terminal!"197197+198198+ with subtest("have the terminal display a colour"):199199+ # We run this command in the background200200+ machine.shell.send(b"(run-in-this-term display-colour |& systemd-cat -t terminal) &\n")201201+202202+ with machine.nested("Waiting for the screen to have pink on it:"):203203+ retry(check_for_pink)204204+ ''}'';205205+}206206+207207+ ) tests
···99, libnotify1010, wrapGAppsHook1111, vte1212+, nixosTests1213}:13141415python3.pkgs.buildPythonApplication rec {···6261 preFixup = ''6362 makeWrapperArgs+=("''${gappsWrapperArgs[@]}")6463 '';6464+6565+ passthru.tests.test = nixosTests.terminal-emulators.terminator;65666667 meta = with lib; {6768 description = "Terminal emulator with support for tiling and tabs";
···99, pcre21010, vte1111, makeWrapper1212+, nixosTests1213}:13141415stdenv.mkDerivation rec {···4241 makeWrapper "$out/bin/wrapped/tilda" "$out/bin/tilda" \4342 --prefix XDG_DATA_DIRS : "$GSETTINGS_SCHEMAS_PATH"4443 '';4444+4545+ passthru.tests.test = nixosTests.terminal-emulators.tilda;45464647 meta = with lib; {4748 description = "A Gtk based drop down terminal for Linux and Unix";
···2222, Cocoa2323, Foundation2424, libiconv2525+, nixosTests2526}:26272728rustPlatform.buildRustPackage rec {···9998 cp -r assets/shell-integration/* "$OUT_APP"10099 ln -s $out/bin/{wezterm,wezterm-mux-server,wezterm-gui,strip-ansi-escapes} "$OUT_APP"101100 '';101101+102102+ passthru.tests.test = nixosTests.terminal-emulators.wezterm;102103103104 meta = with lib; {104105 description = "A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust";