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+
---------------------------------------
# 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 "@_" }
xtrace => 0,
coverage => 0,
restart => 0,
+ xvfb => 1,
);
my $keep_xserver_output = 0;
"valgrind" => \$options{valgrind},
"strace" => \$options{strace},
"xtrace" => \$options{xtrace},
+ "xvfb" => \$options{xvfb},
"display=s" => \@displays,
"parallel=i" => \$parallel,
"help|?" => \$help,
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;
sub cleanup {
my $exitcode = $?;
- $_->() for our @CLEANUP;
+ $_->() for @CLEANUP;
exit $exitcode;
}