Blame soak

Packit 7d6a7d
#!/usr/bin/perl -w
Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  soak -- Test Perl modules with multiple Perl releases.
Packit 7d6a7d
#
Packit 7d6a7d
#  Original Author: Paul Marquess
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
#
Packit 7d6a7d
#  Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
Packit 7d6a7d
#  Version 2.x, Copyright (C) 2001, Paul Marquess.
Packit 7d6a7d
#  Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
Packit 7d6a7d
#
Packit 7d6a7d
#  This program is free software; you can redistribute it and/or
Packit 7d6a7d
#  modify it under the same terms as Perl itself.
Packit 7d6a7d
#
Packit 7d6a7d
################################################################################
Packit 7d6a7d
Packit 7d6a7d
require 5.006001;
Packit 7d6a7d
Packit 7d6a7d
use strict;
Packit 7d6a7d
use warnings;
Packit 7d6a7d
use ExtUtils::MakeMaker;
Packit 7d6a7d
use Getopt::Long;
Packit 7d6a7d
use Pod::Usage;
Packit 7d6a7d
use File::Find;
Packit 7d6a7d
use List::Util qw(max);
Packit 7d6a7d
use Config;
Packit 7d6a7d
Packit 7d6a7d
my $VERSION = '3.36';
Packit 7d6a7d
Packit 7d6a7d
$| = 1;
Packit 7d6a7d
my %OPT = (
Packit 7d6a7d
  verbose => 0,
Packit 7d6a7d
  make    => $Config{make} || 'make',
Packit 7d6a7d
  min     => '5.000',
Packit 7d6a7d
  color   => 1,
Packit 7d6a7d
);
Packit 7d6a7d
Packit 7d6a7d
GetOptions(\%OPT, qw(verbose make=s min=s mmargs=s@ color!)) or pod2usage(2);
Packit 7d6a7d
Packit 7d6a7d
$OPT{mmargs} = [''] unless exists $OPT{mmargs};
Packit 7d6a7d
$OPT{min}    = parse_version($OPT{min}) - 1e-10;
Packit 7d6a7d
Packit 7d6a7d
sub cs($;$$) { my $x = shift; my($s, $p) = @_ ? @_ : ('', 's'); ($x, $x == 1 ? $s : $p) }
Packit 7d6a7d
Packit 7d6a7d
my @GoodPerls = map  { $_->[0] }
Packit 7d6a7d
                sort { $a->[1] <=> $b->[1] or $a->[0] cmp $b->[0] }
Packit 7d6a7d
                grep { $_->[1] >= $OPT{min} }
Packit 7d6a7d
                map  { [$_ => perl_version($_)] }
Packit 7d6a7d
                @ARGV ? SearchPerls(@ARGV) : FindPerls();
Packit 7d6a7d
Packit 7d6a7d
unless (@GoodPerls) {
Packit 7d6a7d
  print "Sorry, got no Perl binaries for testing.\n\n";
Packit 7d6a7d
  exit 0;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
my $maxlen = max(map length, @GoodPerls) + 3;
Packit 7d6a7d
my $mmalen = max(map length, @{$OPT{mmargs}});
Packit 7d6a7d
$maxlen += $mmalen+3 if $mmalen > 0;
Packit 7d6a7d
Packit 7d6a7d
my $rep = Soak::Reporter->new( verbose => $OPT{verbose}
Packit 7d6a7d
                             , color   => $OPT{color}
Packit 7d6a7d
                             , width   => $maxlen
Packit 7d6a7d
                             );
Packit 7d6a7d
Packit 7d6a7d
$SIG{__WARN__} = sub { $rep->warn(@_) };
Packit 7d6a7d
$SIG{__DIE__}  = sub { $rep->die(@_)  };
Packit 7d6a7d
Packit 7d6a7d
# prime the pump, so the first "make realclean" will work.
Packit 7d6a7d
runit("$^X Makefile.PL") && runit("$OPT{make} realclean")
Packit 7d6a7d
    or $rep->die("Cannot run $^X Makefile.PL && $OPT{make} realclean\n");
Packit 7d6a7d
Packit 7d6a7d
my $tot = @GoodPerls*@{$OPT{mmargs}};
Packit 7d6a7d
Packit 7d6a7d
$rep->set(tests => $tot);
Packit 7d6a7d
Packit 7d6a7d
$rep->status(sprintf("Testing %d version%s / %d configuration%s (%d combination%s)...\n",
Packit 7d6a7d
                     cs(@GoodPerls), cs(@{$OPT{mmargs}}), cs($tot)));
Packit 7d6a7d
Packit 7d6a7d
for my $perl (@GoodPerls) {
Packit 7d6a7d
  for my $mm (@{$OPT{mmargs}}) {
Packit 7d6a7d
    $rep->set(perl => $perl, config => $mm);
Packit 7d6a7d
Packit 7d6a7d
    $rep->test;
Packit 7d6a7d
Packit 7d6a7d
    my @warn_mfpl;
Packit 7d6a7d
    my @warn_make;
Packit 7d6a7d
    my @warn_test;
Packit 7d6a7d
Packit 7d6a7d
    my $ok = runit("$perl Makefile.PL $mm", \@warn_mfpl) &&
Packit 7d6a7d
             runit("$OPT{make}", \@warn_make) &&
Packit 7d6a7d
             runit("$OPT{make} test", \@warn_test);
Packit 7d6a7d
Packit 7d6a7d
    $rep->warnings(['Makefile.PL' => \@warn_mfpl],
Packit 7d6a7d
                   ['make'        => \@warn_make],
Packit 7d6a7d
                   ['make test'   => \@warn_test]);
Packit 7d6a7d
Packit 7d6a7d
    if ($ok) {
Packit 7d6a7d
      $rep->passed;
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      $rep->failed;
Packit 7d6a7d
    }
Packit 7d6a7d
Packit 7d6a7d
    runit("$OPT{make} realclean");
Packit 7d6a7d
  }
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
exit $rep->finish;
Packit 7d6a7d
Packit 7d6a7d
sub runit
Packit 7d6a7d
{
Packit 7d6a7d
  # TODO -- portability alert!!
Packit 7d6a7d
Packit 7d6a7d
  my($cmd, $warn) = @_;
Packit 7d6a7d
  $rep->vsay("\n    Running [$cmd]");
Packit 7d6a7d
  my $output = `$cmd 2>&1;;
Packit 7d6a7d
  $output = "\n" unless defined $output;
Packit 7d6a7d
  $output =~ s/^/    > /gm;
Packit 7d6a7d
  $rep->say("\n    Output:\n$output") if $OPT{verbose} || $?;
Packit 7d6a7d
  if ($?) {
Packit 7d6a7d
    $rep->warn("    Running '$cmd' failed: $?\n");
Packit 7d6a7d
    return 0;
Packit 7d6a7d
  }
Packit 7d6a7d
  push @$warn, $output =~ /(warning: .*)/ig;
Packit 7d6a7d
  return 1;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub FindPerls
Packit 7d6a7d
{
Packit 7d6a7d
  # TODO -- need to decide how far back we go.
Packit 7d6a7d
  # TODO -- get list of user releases prior to 5.004
Packit 7d6a7d
  # TODO -- does not work on Windows (at least)
Packit 7d6a7d
Packit 7d6a7d
  # find versions of Perl that are available
Packit 7d6a7d
  my @PerlBinaries = qw(
Packit 7d6a7d
    5.000
Packit 7d6a7d
    5.001
Packit 7d6a7d
    5.002
Packit 7d6a7d
    5.003
Packit 7d6a7d
    5.004 5.00401 5.00402 5.00403 5.00404 5.00405
Packit 7d6a7d
    5.005 5.00501 5.00502 5.00503 5.00504
Packit 7d6a7d
    5.6.0 5.6.1 5.6.2
Packit 7d6a7d
    5.7.0 5.7.1 5.7.2 5.7.3
Packit 7d6a7d
    5.8.0 5.8.1 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.8.8
Packit 7d6a7d
    5.9.0 5.9.1 5.9.2 5.9.3
Packit 7d6a7d
  );
Packit 7d6a7d
Packit 7d6a7d
  print "Searching for Perl binaries...\n";
Packit 7d6a7d
Packit 7d6a7d
  # find_perl will send a warning to STDOUT if it can't find
Packit 7d6a7d
  # the requested perl, so need to temporarily silence STDOUT.
Packit 7d6a7d
  tie *STDOUT, 'NoSTDOUT';
Packit 7d6a7d
Packit 7d6a7d
  my $mm = MM->new( { NAME => 'dummy' });
Packit 7d6a7d
  my @path = $mm->path;
Packit 7d6a7d
  my @GoodPerls;
Packit 7d6a7d
Packit 7d6a7d
  for my $perl (@PerlBinaries) {
Packit 7d6a7d
    if (my $abs = $mm->find_perl($perl, ["perl$perl"], \@path, 0)) {
Packit 7d6a7d
      push @GoodPerls, $abs;
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  untie *STDOUT;
Packit 7d6a7d
Packit 7d6a7d
  print "\nFound:\n", (map "    $_\n", @GoodPerls), "\n";
Packit 7d6a7d
Packit 7d6a7d
  return @GoodPerls;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub SearchPerls
Packit 7d6a7d
{
Packit 7d6a7d
  my @args = @_;
Packit 7d6a7d
  my @perls;
Packit 7d6a7d
Packit 7d6a7d
  for my $arg (@args) {
Packit 7d6a7d
    if (-d $arg) {
Packit 7d6a7d
      my @found;
Packit 7d6a7d
      print "Searching for Perl binaries in '$arg'...\n";
Packit 7d6a7d
      find({ wanted => sub {
Packit 7d6a7d
             $File::Find::name =~ m!perl5[\w._]+$!
Packit 7d6a7d
                 and -f $File::Find::name
Packit 7d6a7d
                 and -x $File::Find::name
Packit 7d6a7d
                 and perl_version($File::Find::name)
Packit 7d6a7d
                 and push @found, $File::Find::name;
Packit 7d6a7d
           }, follow => 1 }, $arg);
Packit 7d6a7d
      printf "Found %d Perl binar%s in '%s'.\n\n", cs(@found, 'y', 'ies'), $arg;
Packit 7d6a7d
      push @perls, @found;
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      push @perls, $arg;
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  return @perls;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub perl_version
Packit 7d6a7d
{
Packit 7d6a7d
  my $perl = shift;
Packit 7d6a7d
  my $ver = `$perl -e 'print \$]' 2>&1;;
Packit 7d6a7d
  return $? == 0 && $ver =~ /^\d+\.\d+/ && $ver >= 5 ? $ver : 0;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub parse_version
Packit 7d6a7d
{
Packit 7d6a7d
  my $ver = shift;
Packit 7d6a7d
Packit 7d6a7d
  if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) {
Packit 7d6a7d
    return $1 + 1e-3*$2 + 1e-6*$3;
Packit 7d6a7d
  }
Packit 7d6a7d
  elsif ($ver =~ /^\d+\.[\d_]+$/) {
Packit 7d6a7d
    $ver =~ s/_//g;
Packit 7d6a7d
    return $ver;
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  die "cannot parse version '$ver'\n";
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
package NoSTDOUT;
Packit 7d6a7d
Packit 7d6a7d
use Tie::Handle;
Packit 7d6a7d
our @ISA = qw(Tie::Handle);
Packit 7d6a7d
Packit 7d6a7d
sub TIEHANDLE { bless \(my $s = ''), shift }
Packit 7d6a7d
sub PRINT {}
Packit 7d6a7d
sub WRITE {}
Packit 7d6a7d
Packit 7d6a7d
package Soak::Reporter;
Packit 7d6a7d
Packit 7d6a7d
use strict;
Packit 7d6a7d
Packit 7d6a7d
sub cs($;$$) { my $x = shift; my($s, $p) = @_ ? @_ : ('', 's'); ($x, $x == 1 ? $s : $p) }
Packit 7d6a7d
Packit 7d6a7d
sub new
Packit 7d6a7d
{
Packit 7d6a7d
  my $class = shift;
Packit 7d6a7d
  bless {
Packit 7d6a7d
    tests   => undef,
Packit 7d6a7d
    color   => 1,
Packit 7d6a7d
    verbose => 0,
Packit 7d6a7d
    @_,
Packit 7d6a7d
    _cur    => 0,
Packit 7d6a7d
    _atbol  => 1,
Packit 7d6a7d
    _total  => 0,
Packit 7d6a7d
    _good   => [],
Packit 7d6a7d
    _bad    => [],
Packit 7d6a7d
  }, $class;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub colored
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
Packit 7d6a7d
  if ($self->{color}) {
Packit 7d6a7d
    my $c = eval {
Packit 7d6a7d
      require Term::ANSIColor;
Packit 7d6a7d
      Term::ANSIColor::colored(@_);
Packit 7d6a7d
    };
Packit 7d6a7d
Packit 7d6a7d
    if ($@) {
Packit 7d6a7d
      $self->{color} = 0;
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      return $c;
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  return $_[0];
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _config
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  return $self->{config} =~ /\S+/ ? " ($self->{config})" : '';
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _progress
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  return '' unless defined $self->{tests};
Packit 7d6a7d
  my $tlen = length $self->{tests};
Packit 7d6a7d
  my $text = sprintf "[%${tlen}d/%${tlen}d] ", $self->{_cur}, $self->{tests};
Packit 7d6a7d
  return $self->colored($text, 'bold');
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _test
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  return $self->_progress . "Testing "
Packit 7d6a7d
         . $self->colored($self->{perl}, 'blue')
Packit 7d6a7d
         . $self->colored($self->_config, 'green');
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _testlen
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  return length("Testing " . $self->{perl} . $self->_config);
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _dots
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  return '.' x $self->_dotslen;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _dotslen
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  return $self->{width} - length($self->{perl} . $self->_config);
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _sep
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  my $width = shift;
Packit 7d6a7d
  $self->print($self->colored('-'x$width, 'bold'), "\n");
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _vsep
Packit 7d6a7d
{
Packit 7d6a7d
  goto &_sep if $_[0]->{verbose};
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub set
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  while (@_) {
Packit 7d6a7d
    my($k, $v) = splice @_, 0, 2;
Packit 7d6a7d
    $self->{$k} = $v;
Packit 7d6a7d
  }
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub test
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->{_cur}++;
Packit 7d6a7d
  $self->_vsep($self->_testlen);
Packit 7d6a7d
  $self->print($self->_test, $self->{verbose} ? "\n" : ' ' . $self->_dots . ' ');
Packit 7d6a7d
  $self->_vsep($self->_testlen);
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _warnings
Packit 7d6a7d
{
Packit 7d6a7d
  my($self, $mode) = @_;
Packit 7d6a7d
Packit 7d6a7d
  my $warnings = 0;
Packit 7d6a7d
  my $differ   = 0;
Packit 7d6a7d
Packit 7d6a7d
  for my $w (@{$self->{_warnings}}) {
Packit 7d6a7d
    if (@{$w->[1]}) {
Packit 7d6a7d
      $warnings += @{$w->[1]};
Packit 7d6a7d
      $differ++;
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  my $rv = '';
Packit 7d6a7d
Packit 7d6a7d
  if ($warnings) {
Packit 7d6a7d
    if ($mode eq 'summary') {
Packit 7d6a7d
      $rv .= sprintf " (%d warning%s", cs($warnings);
Packit 7d6a7d
    }
Packit 7d6a7d
    else {
Packit 7d6a7d
      $rv .= "\n";
Packit 7d6a7d
    }
Packit 7d6a7d
Packit 7d6a7d
    for my $w (@{$self->{_warnings}}) {
Packit 7d6a7d
      if (@{$w->[1]}) {
Packit 7d6a7d
        if ($mode eq 'detail') {
Packit 7d6a7d
          $rv .= "  Warnings during '$w->[0]':\n";
Packit 7d6a7d
          my $cnt = 1;
Packit 7d6a7d
          for my $msg (@{$w->[1]}) {
Packit 7d6a7d
            $rv .= sprintf "    [%d] %s", $cnt++, $msg;
Packit 7d6a7d
          }
Packit 7d6a7d
          $rv .= "\n";
Packit 7d6a7d
        }
Packit 7d6a7d
        else {
Packit 7d6a7d
          unless ($self->{verbose}) {
Packit 7d6a7d
            $rv .= $differ == 1 ? " during " . $w->[0]
Packit 7d6a7d
                                : sprintf(", %d during %s", scalar @{$w->[1]}, $w->[0]);
Packit 7d6a7d
          }
Packit 7d6a7d
        }
Packit 7d6a7d
      }
Packit 7d6a7d
    }
Packit 7d6a7d
Packit 7d6a7d
    if ($mode eq 'summary') {
Packit 7d6a7d
      $rv .= ')';
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  return $rv;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _result
Packit 7d6a7d
{
Packit 7d6a7d
  my($self, $text, $color) = @_;
Packit 7d6a7d
  my $sum = $self->_warnings('summary');
Packit 7d6a7d
  my $len = $self->_testlen + $self->_dotslen + length($text) + length($sum) + 2;
Packit 7d6a7d
Packit 7d6a7d
  $self->_vsep($len);
Packit 7d6a7d
  $self->print($self->_test, ' ', $self->_dots, ' ') if $self->{verbose} || $self->{_atbol};
Packit 7d6a7d
  $self->print($self->colored($text, $color));
Packit 7d6a7d
  $self->print($self->colored($sum, 'red'));
Packit 7d6a7d
  $self->print("\n");
Packit 7d6a7d
  $self->_vsep($len);
Packit 7d6a7d
  $self->print($self->_warnings('detail')) if $self->{verbose};
Packit 7d6a7d
  $self->{_total}++;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub passed
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->_result(@_, 'ok', 'bold green');
Packit 7d6a7d
  push @{$self->{_good}}, [$self->{perl}, $self->{config}];
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub failed
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->_result(@_, 'not ok', 'bold red');
Packit 7d6a7d
  push @{$self->{_bad}}, [$self->{perl}, $self->{config}];
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub warnings
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->{_warnings} = \@_;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub _tobol
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  print "\n" unless $self->{_atbol};
Packit 7d6a7d
  $self->{_atbol} = 1;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub print
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  my $text = join '', @_;
Packit 7d6a7d
  print $text;
Packit 7d6a7d
  $self->{_atbol} = $text =~ /[\r\n]$/;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub say
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->_tobol;
Packit 7d6a7d
  $self->print(@_, "\n");
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub vsay
Packit 7d6a7d
{
Packit 7d6a7d
  goto &say if $_[0]->{verbose};
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub warn
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->say($self->colored(join('', @_), 'red'));
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub die
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
  $self->say($self->colored(join('', 'FATAL: ', @_), 'bold red'));
Packit 7d6a7d
  exit -1;
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub status
Packit 7d6a7d
{
Packit 7d6a7d
  my($self, $text) = @_;
Packit 7d6a7d
  $self->_tobol;
Packit 7d6a7d
  $self->print($self->colored($text, 'bold'), "\n");
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
sub finish
Packit 7d6a7d
{
Packit 7d6a7d
  my $self = shift;
Packit 7d6a7d
Packit 7d6a7d
  if (@{$self->{_bad}}) {
Packit 7d6a7d
    $self->status("\nFailed with:");
Packit 7d6a7d
    for my $fail (@{$self->{_bad}}) {
Packit 7d6a7d
      my($perl, $cfg) = @$fail;
Packit 7d6a7d
      $self->set(config => $cfg);
Packit 7d6a7d
      $self->say("    ", $self->colored($perl, 'blue'), $self->colored($self->_config, 'green'));
Packit 7d6a7d
    }
Packit 7d6a7d
  }
Packit 7d6a7d
Packit 7d6a7d
  $self->status(sprintf("\nPassed with %d of %d combination%s.\n",
Packit 7d6a7d
                        scalar @{$self->{_good}}, cs($self->{_total})));
Packit 7d6a7d
Packit 7d6a7d
  return scalar @{$self->{_bad}};
Packit 7d6a7d
}
Packit 7d6a7d
Packit 7d6a7d
__END__
Packit 7d6a7d
Packit 7d6a7d
=head1 NAME
Packit 7d6a7d
Packit 7d6a7d
soak - Test Perl modules with multiple Perl releases
Packit 7d6a7d
Packit 7d6a7d
=head1 SYNOPSIS
Packit 7d6a7d
Packit 7d6a7d
  soak [options] [perl ...]
Packit 7d6a7d
Packit 7d6a7d
  --make=program     override name of make program ($Config{make})
Packit 7d6a7d
  --min=version      use at least this version of perl
Packit 7d6a7d
  --mmargs=options   pass options to Makefile.PL (multiple --mmargs possible)
Packit 7d6a7d
  --verbose          be verbose
Packit 7d6a7d
  --nocolor          don't use colored output
Packit 7d6a7d
Packit 7d6a7d
=head1 DESCRIPTION
Packit 7d6a7d
Packit 7d6a7d
The F<soak> utility can be used to test Perl modules with
Packit 7d6a7d
multiple Perl releases or build options. It automates the
Packit 7d6a7d
task of running F<Makefile.PL> and the modules test suite.
Packit 7d6a7d
Packit 7d6a7d
It is not primarily intended for cross-platform checking,
Packit 7d6a7d
so don't expect it to work on all platforms.
Packit 7d6a7d
Packit 7d6a7d
=head1 EXAMPLES
Packit 7d6a7d
Packit 7d6a7d
To test your favourite module, just change to its root
Packit 7d6a7d
directory (where the F<Makefile.PL> is located) and run:
Packit 7d6a7d
Packit 7d6a7d
  soak
Packit 7d6a7d
Packit 7d6a7d
This will automatically look for Perl binaries installed
Packit 7d6a7d
on your system.
Packit 7d6a7d
Packit 7d6a7d
Alternatively, you can explicitly pass F<soak> a list of
Packit 7d6a7d
Perl binaries:
Packit 7d6a7d
Packit 7d6a7d
  soak perl5.8.6 perl5.9.2
Packit 7d6a7d
Packit 7d6a7d
Last but not least, you can pass it a list of directories
Packit 7d6a7d
to recursively search for Perl binaries, for example:
Packit 7d6a7d
Packit 7d6a7d
  soak /tmp/perl/install /usr/bin
Packit 7d6a7d
Packit 7d6a7d
All of the above examples will run
Packit 7d6a7d
Packit 7d6a7d
  perl Makefile.PL
Packit 7d6a7d
  make
Packit 7d6a7d
  make test
Packit 7d6a7d
Packit 7d6a7d
for your module and report success or failure.
Packit 7d6a7d
Packit 7d6a7d
If your F<Makefile.PL> can take arguments, you may also
Packit 7d6a7d
want to test different configurations for your module.
Packit 7d6a7d
You can do so with the I<--mmargs> option:
Packit 7d6a7d
Packit 7d6a7d
  soak --mmargs=' ' --mmargs='CCFLAGS=-Wextra' --mmargs='enable-debug'
Packit 7d6a7d
Packit 7d6a7d
This will run
Packit 7d6a7d
Packit 7d6a7d
  perl Makefile.PL
Packit 7d6a7d
  make
Packit 7d6a7d
  make test
Packit 7d6a7d
  perl Makefile.PL CCFLAGS=-Wextra
Packit 7d6a7d
  make
Packit 7d6a7d
  make test
Packit 7d6a7d
  perl Makefile.PL enable-debug
Packit 7d6a7d
  make
Packit 7d6a7d
  make test
Packit 7d6a7d
Packit 7d6a7d
for each Perl binary.
Packit 7d6a7d
Packit 7d6a7d
If you have a directory full of different Perl binaries,
Packit 7d6a7d
but your module isn't expected to work with ancient perls,
Packit 7d6a7d
you can use the I<--min> option to specify the minimum
Packit 7d6a7d
version a Perl binary must have to be chosen for testing:
Packit 7d6a7d
Packit 7d6a7d
  soak --min=5.8.1
Packit 7d6a7d
Packit 7d6a7d
Usually, the output of F<soak> is rather terse, to give
Packit 7d6a7d
you a good overview. If you'd like to see more of what's
Packit 7d6a7d
going on, use the I<--verbose> option:
Packit 7d6a7d
Packit 7d6a7d
  soak --verbose
Packit 7d6a7d
Packit 7d6a7d
=head1 COPYRIGHT
Packit 7d6a7d
Packit 7d6a7d
Version 3.x, Copyright (c) 2004-2013, Marcus Holland-Moritz.
Packit 7d6a7d
Packit 7d6a7d
Version 2.x, Copyright (C) 2001, Paul Marquess.
Packit 7d6a7d
Packit 7d6a7d
Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
Packit 7d6a7d
Packit 7d6a7d
This program is free software; you can redistribute it and/or
Packit 7d6a7d
modify it under the same terms as Perl itself.
Packit 7d6a7d
Packit 7d6a7d
=head1 SEE ALSO
Packit 7d6a7d
Packit 7d6a7d
See L<Devel::PPPort>.
Packit 7d6a7d
Packit 7d6a7d
=cut