From 2e7d406b11d48832e88d3aefd81e84e1cf512dbd Mon Sep 17 00:00:00 2001 From: Jacek Galowicz <jacek.galowicz@cyberus-technology.de> Date: Thu, 6 Feb 2020 14:50:47 +0100 Subject: [PATCH] nixosTests.chromium: Port to Python --- nixos/tests/chromium.nix | 325 +++++++++++++++++++++++---------------- 1 file changed, 195 insertions(+), 130 deletions(-) diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix index 3844255bd8a..fc5d3a5c52f 100644 --- a/nixos/tests/chromium.nix +++ b/nixos/tests/chromium.nix @@ -8,7 +8,7 @@ } }: -with import ../lib/testing.nix { inherit system pkgs; }; +with import ../lib/testing-python.nix { inherit system pkgs; }; with pkgs.lib; mapAttrs (channel: chromiumPkg: makeTest rec { @@ -21,9 +21,11 @@ mapAttrs (channel: chromiumPkg: makeTest rec { enableOCR = true; + user = "alice"; + machine.imports = [ ./common/user-account.nix ./common/x11.nix ]; machine.virtualisation.memorySize = 2047; - machine.test-support.displayManager.auto.user = "alice"; + machine.test-support.displayManager.auto.user = user; machine.environment.systemPackages = [ chromiumPkg ]; startupHTML = pkgs.writeText "chromium-startup.html" '' @@ -47,155 +49,218 @@ mapAttrs (channel: chromiumPkg: makeTest rec { xdoScript = pkgs.writeText "${name}.xdo" text; in "${pkgs.xdotool}/bin/xdotool '${xdoScript}'"; in '' + import shlex + from contextlib import contextmanager, _GeneratorContextManager + + # Run as user alice - sub ru ($) { - my $esc = $_[0] =~ s/'/'\\${"'"}'/gr; - return "su - alice -c '$esc'"; - } + def ru(cmd): + return "su - ${user} -c " + shlex.quote(cmd) - sub createNewWin { - $machine->nest("creating a new Chromium window", sub { - $machine->execute(ru "${xdo "new-window" '' - search --onlyvisible --name "startup done" - windowfocus --sync - windowactivate --sync - ''}"); - $machine->execute(ru "${xdo "new-window" '' - key Ctrl+n - ''}"); - }); - } - sub closeWin { - Machine::retry sub { - $machine->execute(ru "${xdo "close-window" '' - search --onlyvisible --name "new tab" - windowfocus --sync - windowactivate --sync - ''}"); - $machine->execute(ru "${xdo "close-window" '' - key Ctrl+w - ''}"); - for (1..20) { - my ($status, $out) = $machine->execute(ru "${xdo "wait-for-close" '' - search --onlyvisible --name "new tab" - ''}"); - return 1 if $status != 0; - $machine->sleep(1); - } - } - } + def create_new_win(): + with machine.nested("Creating a new Chromium window"): + machine.execute( + ru( + "${xdo "new-window" '' + search --onlyvisible --name "startup done" + windowfocus --sync + windowactivate --sync + ''}" + ) + ) + machine.execute( + ru( + "${xdo "new-window" '' + key Ctrl+n + ''}" + ) + ) - sub waitForNewWin { - my $ret = 0; - $machine->nest("waiting for new Chromium window to appear", sub { - for (1..20) { - my ($status, $out) = $machine->execute(ru "${xdo "wait-for-window" '' - search --onlyvisible --name "new tab" - windowfocus --sync - windowactivate --sync - ''}"); - if ($status == 0) { - $ret = 1; - # XXX: Somehow Chromium is not accepting keystrokes for a few - # seconds after a new window has appeared, so let's wait a while. - $machine->sleep(10); + def close_win(): + def try_close(_): + machine.execute( + ru( + "${xdo "close-window" '' + search --onlyvisible --name "new tab" + windowfocus --sync + windowactivate --sync + ''}" + ) + ) + machine.execute( + ru( + "${xdo "close-window" '' + key Ctrl+w + ''}" + ) + ) + for _ in range(1, 20): + status, out = machine.execute( + ru( + "${xdo "wait-for-close" '' + search --onlyvisible --name "new tab" + ''}" + ) + ) + if status != 0: + return True + machine.sleep(1) + return False - last; - } - $machine->sleep(1); - } - }); - return $ret; - } + retry(try_close) - sub createAndWaitForNewWin { - for (1..3) { - createNewWin; - return 1 if waitForNewWin; - } - die "new window didn't appear within 60 seconds"; - } - sub testNewWin { - my ($desc, $code) = @_; - createAndWaitForNewWin; - subtest($desc, $code); - closeWin; - } + def wait_for_new_win(): + ret = False + with machine.nested("Waiting for new Chromium window to appear"): + for _ in range(1, 20): + status, out = machine.execute( + ru( + "${xdo "wait-for-window" '' + search --onlyvisible --name "new tab" + windowfocus --sync + windowactivate --sync + ''}" + ) + ) + if status == 0: + ret = True + machine.sleep(10) + break + machine.sleep(1) + return ret - $machine->waitForX; - my $url = "file://${startupHTML}"; - $machine->execute(ru "ulimit -c unlimited; chromium \"$url\" & disown"); - $machine->waitForText(qr/startup done/); - $machine->waitUntilSucceeds(ru "${xdo "check-startup" '' - search --sync --onlyvisible --name "startup done" - # close first start help popup - key -delay 1000 Escape - windowfocus --sync - windowactivate --sync - ''}"); + def create_and_wait_for_new_win(): + for _ in range(1, 3): + create_new_win() + if wait_for_new_win(): + return True + assert False, "new window did not appear within 60 seconds" - createAndWaitForNewWin; - $machine->screenshot("empty_windows"); - closeWin; - $machine->screenshot("startup_done"); + @contextmanager + def test_new_win(description): + create_and_wait_for_new_win() + with machine.nested(description): + yield + close_win() - testNewWin "check sandbox", sub { - $machine->succeed(ru "${xdo "type-url" '' - search --sync --onlyvisible --name "new tab" - windowfocus --sync - type --delay 1000 "chrome://sandbox" - ''}"); - $machine->succeed(ru "${xdo "submit-url" '' - search --sync --onlyvisible --name "new tab" - windowfocus --sync - key --delay 1000 Return - ''}"); + machine.wait_for_x() - $machine->screenshot("sandbox_info"); + url = "file://${startupHTML}" + machine.succeed(ru(f'ulimit -c unlimited; chromium "{url}" & disown')) + machine.wait_for_text("startup done") + machine.wait_until_succeeds( + ru( + "${xdo "check-startup" '' + search --sync --onlyvisible --name "startup done" + # close first start help popup + key -delay 1000 Escape + windowfocus --sync + windowactivate --sync + ''}" + ) + ) - $machine->succeed(ru "${xdo "find-window" '' - search --sync --onlyvisible --name "sandbox status" - windowfocus --sync - ''}"); - $machine->succeed(ru "${xdo "copy-sandbox-info" '' - key --delay 1000 Ctrl+a Ctrl+c - ''}"); + create_and_wait_for_new_win() + machine.screenshot("empty_windows") + close_win() - my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o"); - die "sandbox not working properly: $clipboard" - unless $clipboard =~ /layer 1 sandbox.*namespace/mi - && $clipboard =~ /pid namespaces.*yes/mi - && $clipboard =~ /network namespaces.*yes/mi - && $clipboard =~ /seccomp.*sandbox.*yes/mi - && $clipboard =~ /you are adequately sandboxed/mi; + machine.screenshot("startup_done") - $machine->sleep(1); - $machine->succeed(ru "${xdo "find-window-after-copy" '' - search --onlyvisible --name "sandbox status" - ''}"); + with test_new_win("check sandbox"): + machine.succeed( + ru( + "${xdo "type-url" '' + search --sync --onlyvisible --name "new tab" + windowfocus --sync + type --delay 1000 "chrome://sandbox" + ''}" + ) + ) - my $clipboard = $machine->succeed(ru "echo void | ${pkgs.xclip}/bin/xclip -i"); - $machine->succeed(ru "${xdo "copy-sandbox-info" '' - key --delay 1000 Ctrl+a Ctrl+c - ''}"); + machine.succeed( + ru( + "${xdo "submit-url" '' + search --sync --onlyvisible --name "new tab" + windowfocus --sync + key --delay 1000 Return + ''}" + ) + ) - my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o"); - die "copying twice in a row does not work properly: $clipboard" - unless $clipboard =~ /layer 1 sandbox.*namespace/mi - && $clipboard =~ /pid namespaces.*yes/mi - && $clipboard =~ /network namespaces.*yes/mi - && $clipboard =~ /seccomp.*sandbox.*yes/mi - && $clipboard =~ /you are adequately sandboxed/mi; + machine.screenshot("sandbox_info") - $machine->screenshot("afer_copy_from_chromium"); - }; + machine.succeed( + ru( + "${xdo "find-window" '' + search --sync --onlyvisible --name "sandbox status" + windowfocus --sync + ''}" + ) + ) + machine.succeed( + ru( + "${xdo "copy-sandbox-info" '' + key --delay 1000 Ctrl+a Ctrl+c + ''}" + ) + ) - $machine->shutdown; + clipboard = machine.succeed( + ru("${pkgs.xclip}/bin/xclip -o") + ) + + filters = [ + "layer 1 sandbox.*namespace", + "pid namespaces.*yes", + "network namespaces.*yes", + "seccomp.*sandbox.*yes", + "you are adequately sandboxed", + ] + if not all( + re.search(filter, clipboard, flags=re.DOTALL | re.IGNORECASE) + for filter in filters + ): + assert False, f"sandbox not working properly: {clipboard}" + + machine.sleep(1) + machine.succeed( + ru( + "${xdo "find-window-after-copy" '' + search --onlyvisible --name "sandbox status" + ''}" + ) + ) + + clipboard = machine.succeed( + ru( + "echo void | ${pkgs.xclip}/bin/xclip -i" + ) + ) + machine.succeed( + ru( + "${xdo "copy-sandbox-info" '' + key --delay 1000 Ctrl+a Ctrl+c + ''}" + ) + ) + + clipboard = machine.succeed( + ru("${pkgs.xclip}/bin/xclip -o") + ) + if not all( + re.search(filter, clipboard, flags=re.DOTALL | re.IGNORECASE) + for filter in filters + ): + assert False, f"copying twice in a row does not work properly: {clipboard}" + + machine.screenshot("after_copy_from_chromium") + + machine.shutdown() ''; }) channelMap