diff options
Diffstat (limited to 'nixos/tests')
-rw-r--r-- | nixos/tests/all-tests.nix | 2 | ||||
-rw-r--r-- | nixos/tests/terminal-emulators.nix | 207 | ||||
-rw-r--r-- | nixos/tests/web-apps/mastodon.nix | 170 | ||||
-rw-r--r-- | nixos/tests/wine.nix | 13 |
4 files changed, 389 insertions, 3 deletions
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index b2b35119ce3..474bb423379 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -286,6 +286,7 @@ in mailhog = handleTest ./mailhog.nix {}; man = handleTest ./man.nix {}; mariadb-galera = handleTest ./mysql/mariadb-galera.nix {}; + mastodon = handleTestOn ["x86_64-linux" "i686-linux" "aarch64-linux"] ./web-apps/mastodon.nix {}; matomo = handleTest ./matomo.nix {}; matrix-appservice-irc = handleTest ./matrix-appservice-irc.nix {}; matrix-conduit = handleTest ./matrix-conduit.nix {}; @@ -521,6 +522,7 @@ in telegraf = handleTest ./telegraf.nix {}; teleport = handleTest ./teleport.nix {}; thelounge = handleTest ./thelounge.nix {}; + terminal-emulators = handleTest ./terminal-emulators.nix {}; tiddlywiki = handleTest ./tiddlywiki.nix {}; tigervnc = handleTest ./tigervnc.nix {}; timezone = handleTest ./timezone.nix {}; diff --git a/nixos/tests/terminal-emulators.nix b/nixos/tests/terminal-emulators.nix new file mode 100644 index 00000000000..60161b80b96 --- /dev/null +++ b/nixos/tests/terminal-emulators.nix @@ -0,0 +1,207 @@ +# Terminal emulators all present a pretty similar interface. +# That gives us an opportunity to easily test their basic functionality with a single codebase. +# +# There are two tests run on each terminal emulator +# - can it successfully execute a command passed on the cmdline? +# - can it successfully display a colour? +# the latter is used as a proxy for "can it display text?", without going through all the intricacies of OCR. +# +# 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). +# +# Future work: +# - Wayland support (both for testing the existing terminals, and for testing wayland-only terminals like foot and havoc) +# - Test keyboard input? (skipped for now, to eliminate the possibility of race conditions and focus issues) + +{ system ? builtins.currentSystem, + config ? {}, + pkgs ? import ../.. { inherit system config; } +}: + +with import ../lib/testing-python.nix { inherit system pkgs; }; +with pkgs.lib; + +let tests = { + alacritty.pkg = p: p.alacritty; + + contour.pkg = p: p.contour; + contour.cmd = "contour $command"; + + cool-retro-term.pkg = p: p.cool-retro-term; + cool-retro-term.colourTest = false; # broken by gloss effect + + ctx.pkg = p: p.ctx; + ctx.pinkValue = "#FE0065"; + + darktile.pkg = p: p.darktile; + + eterm.pkg = p: p.eterm; + eterm.executable = "Eterm"; + eterm.pinkValue = "#D40055"; + + germinal.pkg = p: p.germinal; + + gnome-terminal.pkg = p: p.gnome.gnome-terminal; + + guake.pkg = p: p.guake; + guake.cmd = "SHELL=$command guake --show"; + guake.kill = true; + + hyper.pkg = p: p.hyper; + + kermit.pkg = p: p.kermit-terminal; + + kgx.pkg = p: p.kgx; + kgx.cmd = "kgx -e $command"; + kgx.kill = true; + + kitty.pkg = p: p.kitty; + kitty.cmd = "kitty $command"; + + konsole.pkg = p: p.plasma5Packages.konsole; + + lxterminal.pkg = p: p.lxterminal; + + mate-terminal.pkg = p: p.mate.mate-terminal; + mate-terminal.cmd = "SHELL=$command mate-terminal --disable-factory"; # factory mode uses dbus, and we don't have a proper dbus session set up + + mlterm.pkg = p: p.mlterm; + + mrxvt.pkg = p: p.mrxvt; + + qterminal.pkg = p: p.lxqt.qterminal; + qterminal.kill = true; + + roxterm.pkg = p: p.roxterm; + roxterm.cmd = "roxterm -e $command"; + + sakura.pkg = p: p.sakura; + + st.pkg = p: p.st; + st.kill = true; + + stupidterm.pkg = p: p.stupidterm; + stupidterm.cmd = "stupidterm -- $command"; + + terminator.pkg = p: p.terminator; + terminator.cmd = "terminator -e $command"; + + terminology.pkg = p: p.enlightenment.terminology; + terminology.cmd = "SHELL=$command terminology --no-wizard=true"; + terminology.colourTest = false; # broken by gloss effect + + termite.pkg = p: p.termite; + + termonad.pkg = p: p.termonad; + + tilda.pkg = p: p.tilda; + + tilix.pkg = p: p.tilix; + tilix.cmd = "tilix -e $command"; + + urxvt.pkg = p: p.rxvt-unicode; + + wayst.pkg = p: p.wayst; + wayst.pinkValue = "#FF0066"; + + wezterm.pkg = p: p.wezterm; + + xfce4-terminal.pkg = p: p.xfce.xfce4-terminal; + + xterm.pkg = p: p.xterm; + }; +in mapAttrs (name: { pkg, executable ? name, cmd ? "SHELL=$command ${executable}", colourTest ? true, pinkValue ? "#FF0087", kill ? false }: makeTest +{ + name = "terminal-emulator-${name}"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ jjjollyjim ]; + }; + + machine = { pkgsInner, ... }: + + { + imports = [ ./common/x11.nix ./common/user-account.nix ]; + + # Hyper (and any other electron-based terminals) won't run as root + test-support.displayManager.auto.user = "alice"; + + environment.systemPackages = [ + (pkg pkgs) + (pkgs.writeShellScriptBin "report-success" '' + echo 1 > /tmp/term-ran-successfully + ${optionalString kill "pkill ${executable}"} + '') + (pkgs.writeShellScriptBin "display-colour" '' + # A 256-colour background colour code for pink, then spaces. + # + # Background is used rather than foreground to minimize the effect of anti-aliasing. + # + # Keep adding more in case the window is partially offscreen to the left or requires + # a change to correctly redraw after initialising the window (as with ctx). + + while : + do + echo -ne "\e[48;5;198m " + sleep 0.5 + done + sleep infinity + '') + (pkgs.writeShellScriptBin "run-in-this-term" "sudo -u alice run-in-this-term-wrapped $1") + + (pkgs.writeShellScriptBin "run-in-this-term-wrapped" "command=\"$(which \"$1\")\"; ${cmd}") + ]; + + # Helpful reminder to add this test to passthru.tests + warnings = if !((pkg pkgs) ? "passthru" && (pkg pkgs).passthru ? "tests") then [ "The package for ${name} doesn't have a passthru.tests" ] else [ ]; + }; + + # We need imagemagick, though not tesseract + enableOCR = true; + + testScript = { nodes, ... }: let + in '' + with subtest("wait for x"): + start_all() + machine.wait_for_x() + + with subtest("have the terminal run a command"): + # We run this command synchronously, so we can be certain the exit codes are happy + machine.${if kill then "execute" else "succeed"}("run-in-this-term report-success") + machine.wait_for_file("/tmp/term-ran-successfully") + ${optionalString colourTest '' + + import tempfile + import subprocess + + + def check_for_pink(final=False) -> bool: + with tempfile.NamedTemporaryFile() as tmpin: + machine.send_monitor_command("screendump {}".format(tmpin.name)) + + cmd = 'convert {} -define histogram:unique-colors=true -format "%c" histogram:info:'.format( + tmpin.name + ) + ret = subprocess.run(cmd, shell=True, capture_output=True) + if ret.returncode != 0: + raise Exception( + "image analysis failed with exit code {}".format(ret.returncode) + ) + + text = ret.stdout.decode("utf-8") + return "${pinkValue}" in text + + + with subtest("ensuring no pink is present without the terminal"): + assert ( + check_for_pink() == False + ), "Pink was present on the screen before we even launched a terminal!" + + with subtest("have the terminal display a colour"): + # We run this command in the background + machine.shell.send(b"(run-in-this-term display-colour |& systemd-cat -t terminal) &\n") + + with machine.nested("Waiting for the screen to have pink on it:"): + retry(check_for_pink) + ''}''; +} + + ) tests diff --git a/nixos/tests/web-apps/mastodon.nix b/nixos/tests/web-apps/mastodon.nix new file mode 100644 index 00000000000..279a1c59169 --- /dev/null +++ b/nixos/tests/web-apps/mastodon.nix @@ -0,0 +1,170 @@ +import ../make-test-python.nix ({pkgs, ...}: +let + test-certificates = pkgs.runCommandLocal "test-certificates" { } '' + mkdir -p $out + echo insecure-root-password > $out/root-password-file + echo insecure-intermediate-password > $out/intermediate-password-file + ${pkgs.step-cli}/bin/step certificate create "Example Root CA" $out/root_ca.crt $out/root_ca.key --password-file=$out/root-password-file --profile root-ca + ${pkgs.step-cli}/bin/step certificate create "Example Intermediate CA 1" $out/intermediate_ca.crt $out/intermediate_ca.key --password-file=$out/intermediate-password-file --ca-password-file=$out/root-password-file --profile intermediate-ca --ca $out/root_ca.crt --ca-key $out/root_ca.key + ''; + + hosts = '' + 192.168.2.10 ca.local + 192.168.2.11 mastodon.local + ''; + +in +{ + name = "mastodon"; + meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin ]; + + nodes = { + ca = { pkgs, ... }: { + networking = { + interfaces.eth1 = { + ipv4.addresses = [ + { address = "192.168.2.10"; prefixLength = 24; } + ]; + }; + extraHosts = hosts; + }; + services.step-ca = { + enable = true; + address = "0.0.0.0"; + port = 8443; + openFirewall = true; + intermediatePasswordFile = "${test-certificates}/intermediate-password-file"; + settings = { + dnsNames = [ "ca.local" ]; + root = "${test-certificates}/root_ca.crt"; + crt = "${test-certificates}/intermediate_ca.crt"; + key = "${test-certificates}/intermediate_ca.key"; + db = { + type = "badger"; + dataSource = "/var/lib/step-ca/db"; + }; + authority = { + provisioners = [ + { + type = "ACME"; + name = "acme"; + } + ]; + }; + }; + }; + }; + + server = { pkgs, ... }: { + networking = { + interfaces.eth1 = { + ipv4.addresses = [ + { address = "192.168.2.11"; prefixLength = 24; } + ]; + }; + extraHosts = hosts; + firewall.allowedTCPPorts = [ 80 443 ]; + }; + + security = { + acme = { + acceptTerms = true; + defaults.server = "https://ca.local:8443/acme/acme/directory"; + defaults.email = "mastodon@mastodon.local"; + }; + pki.certificateFiles = [ "${test-certificates}/root_ca.crt" ]; + }; + + services.redis.servers.mastodon = { + enable = true; + bind = "127.0.0.1"; + port = 31637; + }; + + services.mastodon = { + enable = true; + configureNginx = true; + localDomain = "mastodon.local"; + enableUnixSocket = false; + redis = { + createLocally = true; + host = "127.0.0.1"; + port = 31637; + }; + database = { + createLocally = true; + host = "/run/postgresql"; + port = 5432; + }; + smtp = { + createLocally = false; + fromAddress = "mastodon@mastodon.local"; + }; + extraConfig = { + EMAIL_DOMAIN_ALLOWLIST = "example.com"; + }; + }; + }; + + client = { pkgs, ... }: { + environment.systemPackages = [ pkgs.jq ]; + networking = { + interfaces.eth1 = { + ipv4.addresses = [ + { address = "192.168.2.12"; prefixLength = 24; } + ]; + }; + extraHosts = hosts; + }; + + security = { + pki.certificateFiles = [ "${test-certificates}/root_ca.crt" ]; + }; + }; + }; + + testScript = '' + start_all() + + ca.wait_for_unit("step-ca.service") + ca.wait_for_open_port(8443) + + server.wait_for_unit("nginx.service") + server.wait_for_unit("redis-mastodon.service") + server.wait_for_unit("postgresql.service") + server.wait_for_unit("mastodon-sidekiq.service") + server.wait_for_unit("mastodon-streaming.service") + server.wait_for_unit("mastodon-web.service") + server.wait_for_open_port(55000) + server.wait_for_open_port(55001) + + # Check Mastodon version from remote client + client.succeed("curl --fail https://mastodon.local/api/v1/instance | jq -r '.version' | grep '${pkgs.mastodon.version}'") + + # Check using admin CLI + # Check Mastodon version + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl version' | grep '${pkgs.mastodon.version}'") + + # Manage accounts + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl email_domain_blocks add example.com'") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl email_domain_blocks list' | grep 'example.com'") + server.fail("su - mastodon -s /bin/sh -c 'mastodon-env tootctl email_domain_blocks list' | grep 'mastodon.local'") + server.fail("su - mastodon -s /bin/sh -c 'mastodon-env tootctl accounts create alice --email=alice@example.com'") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl email_domain_blocks remove example.com'") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl accounts create bob --email=bob@example.com'") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl accounts approve bob'") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl accounts delete bob'") + + # Manage IP access + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl ip_blocks add 192.168.0.0/16 --severity=no_access'") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl ip_blocks export' | grep '192.168.0.0/16'") + server.fail("su - mastodon -s /bin/sh -c 'mastodon-env tootctl p_blocks export' | grep '172.16.0.0/16'") + client.fail("curl --fail https://mastodon.local/about") + server.succeed("su - mastodon -s /bin/sh -c 'mastodon-env tootctl ip_blocks remove 192.168.0.0/16'") + client.succeed("curl --fail https://mastodon.local/about") + + ca.shutdown() + server.shutdown() + client.shutdown() + ''; +}) diff --git a/nixos/tests/wine.nix b/nixos/tests/wine.nix index cc449864c76..8135cb90a59 100644 --- a/nixos/tests/wine.nix +++ b/nixos/tests/wine.nix @@ -3,7 +3,7 @@ }: let - inherit (pkgs.lib) concatMapStrings listToAttrs; + inherit (pkgs.lib) concatMapStrings listToAttrs optionals optionalString; inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest; hello32 = "${pkgs.pkgsCross.mingw32.hello}/bin/hello.exe"; @@ -27,6 +27,9 @@ let "bash -c 'wine ${exe} 2> >(tee wine-stderr >&2)'" ) assert 'Hello, world!' in greeting + '' + # only the full version contains Gecko, but the error is not printed reliably in other variants + + optionalString (variant == "full") '' machine.fail( "fgrep 'Could not find Wine Gecko. HTML rendering will be disabled.' wine-stderr" ) @@ -37,5 +40,9 @@ let variants = [ "base" "full" "minimal" "staging" "unstable" "wayland" ]; -in listToAttrs (map (makeWineTest "winePackages" [ hello32 ]) variants - ++ map (makeWineTest "wineWowPackages" [ hello32 hello64 ]) variants) +in +listToAttrs ( + map (makeWineTest "winePackages" [ hello32 ]) variants + ++ optionals pkgs.stdenv.is64bit + (map (makeWineTest "wineWowPackages" [ hello32 hello64 ]) variants) +) |