From: Michael Stapelberg Date: Fri, 13 Oct 2017 07:18:49 +0000 (-0700) Subject: tests: run under Xvfb by default (if available) (#2951) X-Git-Tag: 4.15~53 X-Git-Url: https://git.sur5r.net/?p=i3%2Fi3;a=commitdiff_plain;h=44a6efb5b0160718f66fe39172299a523d55cedb tests: run under Xvfb by default (if available) (#2951) This shaves off two seconds of wall-clock time (10s → 8s). --- diff --git a/docs/testsuite b/docs/testsuite index bf85cb1f..b535e7c1 100644 --- a/docs/testsuite +++ b/docs/testsuite @@ -113,10 +113,8 @@ containing the appropriate i3 logfile for each testcase. The latest folder can always be found under the symlink +latest/+. Unless told differently, it will run the tests on a separate X server instance (using Xephyr). -Xephyr will open a window where you can inspect the running test. You can run -the tests without an X session with Xvfb, such as with +xvfb-run -./complete-run+. This will also speed up the tests significantly especially on -machines without a powerful video card. +Xephyr will open a window where you can inspect the running test. By default, +tests are run under Xvfb. .Example invocation of +complete-run.pl+ --------------------------------------- diff --git a/testcases/complete-run.pl.in b/testcases/complete-run.pl.in index ddd6ccad..b7b39872 100755 --- a/testcases/complete-run.pl.in +++ b/testcases/complete-run.pl.in @@ -38,6 +38,8 @@ binmode STDERR, ':utf8'; # subshell or situations like that. AnyEvent::Util::close_all_fds_except(0, 1, 2); +our @CLEANUP; + # convenience wrapper to write to the log file my $log; sub Log { say $log "@_" } @@ -55,6 +57,7 @@ my %options = ( xtrace => 0, coverage => 0, restart => 0, + xvfb => 1, ); my $keep_xserver_output = 0; @@ -64,6 +67,7 @@ my $result = GetOptions( "valgrind" => \$options{valgrind}, "strace" => \$options{strace}, "xtrace" => \$options{xtrace}, + "xvfb" => \$options{xvfb}, "display=s" => \@displays, "parallel=i" => \$parallel, "help|?" => \$help, @@ -112,6 +116,44 @@ $ENV{PATH} = join(':', qx(Xephyr -help 2>&1); die "Xephyr was not found in your path. Please install Xephyr (xserver-xephyr on Debian)." if $?; +qx(xvfb-run --help 2>&1); +if ($? && $options{xvfb}) { + say "xvfb-run not found, not running tests under xvfb. Install the xvfb package to speed up tests"; + $options{xvfb} = 0; +} + +if ($options{xvfb}) { + for (my $n = 99; $n < 120; $n++) { + my $path = File::Temp::tmpnam($ENV{TMPDIR} // "/tmp", "i3-testsXXXXXX"); + if (!defined(POSIX::mkfifo($path, 0600))) { + die "mkfifo: $!"; + } + my $pid = fork // die "fork: $!"; + if ($pid == 0) { + # Child + + # Xvfb checks whether the parent ignores USR1 and sends USR1 to the + # parent when ready, so that the wait call will be interrupted. We + # can’t implement this in Perl, as Perl’s waitpid transparently + # handles -EINTR. + exec('/bin/sh', '-c', qq|trap "exit" INT; trap : USR1; (trap '' USR1; exec Xvfb :$n -screen 0 640x480x8 -nolisten tcp) & PID=\$!; wait; if ! kill -0 \$PID 2>/dev/null; then echo 1:\$PID > $path; else echo 0:\$PID > $path; wait \$PID; fi|); + die "exec: $!"; + } + chomp(my $kill = slurp($path)); + unlink($path); + my ($code, $xvfbpid) = ($kill =~ m,^([0-1]):(.*)$,); + next unless $code eq '0'; + + $ENV{DISPLAY} = ":$n"; + say "Running tests under Xvfb display $ENV{DISPLAY}"; + + push(@CLEANUP, sub { + kill(15, $xvfbpid); + }); + last; + } +} + @displays = split(/,/, join(',', @displays)); @displays = map { s/ //g; $_ } @displays; @@ -379,7 +421,7 @@ sub take_job { sub cleanup { my $exitcode = $?; - $_->() for our @CLEANUP; + $_->() for @CLEANUP; exit $exitcode; } diff --git a/travis/run-tests.sh b/travis/run-tests.sh index 44df81d2..eac2ea8a 100755 --- a/travis/run-tests.sh +++ b/travis/run-tests.sh @@ -26,7 +26,7 @@ fi # Try running the tests in parallel so that the common case (tests pass) is # quick, but fall back to running them in sequence to make debugging easier. -if ! xvfb-run make check +if ! make check then - xvfb-run ./testcases/complete-run.pl --parallel=1 || (cat latest/complete-run.log; false) + ./testcases/complete-run.pl --parallel=1 || (cat latest/complete-run.log; false) fi