complete-run.pl: automatically start Xdummy instances unless -d is specified

This makes running the testsuite incredibly easy:
    $ ./complete-run.pl
:)
next
Michael Stapelberg 2011-11-07 23:04:45 +00:00
parent 8b887e8447
commit afc488021f
3 changed files with 124 additions and 10 deletions

View File

@ -1,13 +1,6 @@
#!/usr/bin/env perl
# vim:ts=4:sw=4:expandtab
#
# © 2010-2011 Michael Stapelberg and contributors
#
# syntax: ./complete-run.pl --display :1 --display :2
# to run the test suite on the X11 displays :1 and :2
# use 'Xdummy :1' and 'Xdummy :2' before to start two
# headless X11 servers
#
use strict;
use warnings;
@ -28,6 +21,7 @@ use TAP::Parser::Aggregator;
# these are shipped with the testsuite
use lib qw(lib);
use SocketActivation;
use StartXDummy;
# the following modules are not shipped with Perl
use AnyEvent;
use AnyEvent::Handle;
@ -46,7 +40,7 @@ $SIG{CHLD} = sub {
# reads in a whole file
sub slurp {
open my $fh, '<', shift;
open(my $fh, '<', shift);
local $/;
<$fh>;
}
@ -54,21 +48,32 @@ sub slurp {
my $coverage_testing = 0;
my $valgrind = 0;
my $help = 0;
# Number of tests to run in parallel. Important to know how many Xdummy
# instances we need to start (unless @displays are given). Defaults to
# num_cores * 2.
my $parallel = undef;
my @displays = ();
my @childpids = ();
my $result = GetOptions(
"coverage-testing" => \$coverage_testing,
"valgrind" => \$valgrind,
"display=s" => \@displays,
"parallel=i" => \$parallel,
"help|?" => \$help,
);
pod2usage(0) if $help;
pod2usage(-verbose => 2, -exitcode => 0) if $help;
@displays = split(/,/, join(',', @displays));
@displays = map { s/ //g; $_ } @displays;
@displays = qw(:1) if @displays == 0;
# No displays specified, lets start some Xdummy instances.
if (@displays == 0) {
my ($displays, $pids) = start_xdummy($parallel);
@displays = @$displays;
@childpids = @$pids;
}
# connect to all displays for two reasons:
# 1: check if the display actually works
@ -88,6 +93,8 @@ for my $display (@displays) {
}
}
die "No usable displays found" if @wdisplays == 0;
my $config = slurp('i3-test.config');
# 1: get a list of all testcases
@ -268,6 +275,9 @@ $cv->recv;
$aggregator->stop();
# Disable buffering to make sure the output and summary appear before we exit.
$| = 1;
for (@done) {
my ($test, $output) = @$_;
say "output for $test:";
@ -277,6 +287,8 @@ for (@done) {
# 4: print summary
$harness->summary($aggregator);
kill(15, $_) for @childpids;
__END__
=head1 NAME
@ -287,6 +299,15 @@ complete-run.pl - Run the i3 testsuite
complete-run.pl [files...]
=head1 EXAMPLE
To run the whole testsuite on a reasonable number of Xdummy instances (your
running X11 will not be touched), run:
./complete-run.pl
To run only a specific test (useful when developing a new feature), run:
./complete-run t/100-fullscreen.t
=head1 OPTIONS
=over 8
@ -302,6 +323,9 @@ will parallelize the tests:
# Run four tests in parallel on some Xdummy servers
./complete-run.pl -d :1,:2,:3,:4
Note that it is not necessary to specify this anymore. If omitted,
complete-run.pl will start (num_cores * 2) Xdummy instances.
=item B<--valgrind>
Runs i3 under valgrind to find memory problems. The output will be available in
@ -310,3 +334,11 @@ C<latest/valgrind.log>.
=item B<--coverage-testing>
Exits i3 cleanly (instead of kill -9) to make coverage testing work properly.
=item B<--parallel>
Number of Xdummy instances to start (if you dont want to start num_cores * 2
instances for some reason).
# Run all tests on a single Xdummy instance
./complete-run.pl -p 1

View File

@ -1,6 +1,8 @@
package SocketActivation;
# vim:ts=4:sw=4:expandtab
use strict;
use warnings;
use IO::Socket::UNIX; # core
use Cwd qw(abs_path); # core
use POSIX; # core

View File

@ -0,0 +1,80 @@
package StartXDummy;
# vim:ts=4:sw=4:expandtab
use strict;
use warnings;
use POSIX ();
use Exporter 'import';
use Time::HiRes qw(sleep);
use v5.10;
our @EXPORT = qw(start_xdummy);
# reads in a whole file
sub slurp {
open(my $fh, '<', shift) or return '';
local $/;
<$fh>;
}
=head2 start_xdummy($parallel)
Starts C<$parallel> (or number of cores * 2 if undef) Xdummy processes (see
the file ./Xdummy) and returns two arrayrefs: a list of X11 display numbers to
the Xdummy processes and a list of PIDs of the processes.
=cut
sub start_xdummy {
my ($parallel) = @_;
my @displays = ();
my @childpids = ();
# Yeah, I know its non-standard, but Perls POSIX module doesnt have
# _SC_NPROCESSORS_CONF.
my $cpuinfo = slurp('/proc/cpuinfo');
my $num_cores = scalar grep { /model name/ } split("\n", $cpuinfo);
# If /proc/cpuinfo does not exist, we fall back to 2 cores.
$num_cores ||= 2;
$parallel ||= $num_cores * 2;
# First get the last used display number, then increment it by one.
# Effectively falls back to 1 if no X server is running.
my ($displaynum) = reverse ('0', sort </tmp/.X11-unix/X*>);
$displaynum =~ s/.*(\d)$/$1/;
$displaynum++;
say "Starting $parallel Xdummy instances, starting at :$displaynum...";
for my $idx (0 .. ($parallel-1)) {
my $pid = fork();
die "Could not fork: $!" unless defined($pid);
if ($pid == 0) {
# Child, close stdout/stderr, then start Xdummy.
POSIX::close(0);
POSIX::close(2);
exec './Xdummy', ":$displaynum", '-config', '/dev/null';
exit 1;
}
push(@childpids, $pid);
push(@displays, ":$displaynum");
$displaynum++;
}
# Wait until the X11 sockets actually appear. Pretty ugly solution, but as
# long as we cant socket-activate X11…
my $sockets_ready;
do {
$sockets_ready = 1;
for (@displays) {
my $path = "/tmp/.X11-unix/X" . substr($_, 1);
$sockets_ready = 0 unless -S $path;
}
sleep 0.1;
} until $sockets_ready;
return \@displays, \@childpids;
}
1