]> git.sur5r.net Git - i3/i3/commitdiff
complete-run.pl: automatically start Xdummy instances unless -d is specified
authorMichael Stapelberg <michael@stapelberg.de>
Mon, 7 Nov 2011 23:04:45 +0000 (23:04 +0000)
committerMichael Stapelberg <michael@stapelberg.de>
Mon, 7 Nov 2011 23:04:45 +0000 (23:04 +0000)
This makes running the testsuite incredibly easy:
    $ ./complete-run.pl
:)

testcases/complete-run.pl
testcases/lib/SocketActivation.pm
testcases/lib/StartXDummy.pm [new file with mode: 0644]

index 2f05f703e2a695622f26b2d505c72b8db4a861ed..915a7e02679a1978cca5ab156ac0c5e22103650f 100755 (executable)
@@ -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, let’s 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 don’t want to start num_cores * 2
+instances for some reason).
+
+  # Run all tests on a single Xdummy instance
+  ./complete-run.pl -p 1
index 47a709d59ef013f712851239851aafa46b48864e..31b3ba896400aed58aeea900c44475cdf71eb744 100644 (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
diff --git a/testcases/lib/StartXDummy.pm b/testcases/lib/StartXDummy.pm
new file mode 100644 (file)
index 0000000..8657ba9
--- /dev/null
@@ -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 it’s non-standard, but Perl’s POSIX module doesn’t 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 can’t 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