326 lines
7.5 KiB
Plaintext
326 lines
7.5 KiB
Plaintext
|
#!/usr/bin/perl -w
|
||
|
#----------------------------------------------------------------------
|
||
|
# Copyright 1999-2003 Mitel Networks Corporation
|
||
|
# This program is free software; you can redistribute it and/or
|
||
|
# modify it under the same terms as Perl itself.
|
||
|
#----------------------------------------------------------------------
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
quicktest - quickly run all tests in the current CVS project
|
||
|
|
||
|
=head1 SYNOPSIS
|
||
|
|
||
|
quicktest
|
||
|
quicktest [files ...] [--verbose]
|
||
|
|
||
|
quicktest [-d] [--verbose] file
|
||
|
|
||
|
|
||
|
=head1 DESCRIPTION
|
||
|
|
||
|
This is a little script to let you quickly run your tests while making
|
||
|
changes to an existing e-smith RPM project.
|
||
|
|
||
|
Unless given a specific set of files to run, it will run all .t files
|
||
|
and embedded tests in the current CVS project. It allows you to do a
|
||
|
quick test of the RPM without having to do much figuring or typing.
|
||
|
|
||
|
It will also use any perl libraries located in the current CVS
|
||
|
project.
|
||
|
|
||
|
The "current CVS project" is defined by whatever CVS project you're
|
||
|
current working directory is in. So if you're sitting in
|
||
|
~/devel/e-smith-base/root/usr/ it will assume your project is
|
||
|
e-smith-base.
|
||
|
|
||
|
Emacs backup files, CVS backup files and other temporary and backup
|
||
|
files will be automatically skipped.
|
||
|
|
||
|
All tests will be run with warnings on.
|
||
|
|
||
|
=head2 Switches
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item B<-d>
|
||
|
|
||
|
Tells quicktest to run the test in the debugger. It will gracefully
|
||
|
handle embedded tests.
|
||
|
|
||
|
quicktest -d lib/some/module.pm
|
||
|
|
||
|
=item B<--verbose>
|
||
|
|
||
|
With --verbose quicktest will print out all the lines received from
|
||
|
the test.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head1 FILES
|
||
|
|
||
|
CVS/Repository
|
||
|
|
||
|
=head1 AUTHOR
|
||
|
|
||
|
Mitel Networks Corporation.
|
||
|
|
||
|
For more information, see http://www.e-smith.org/
|
||
|
|
||
|
=cut
|
||
|
|
||
|
use strict;
|
||
|
use File::Find;
|
||
|
use File::Spec;
|
||
|
|
||
|
$| = 1;
|
||
|
|
||
|
open(my $repository, 'CVS/Repository') ||
|
||
|
die "Can't find a CVS/Repository to look at: $!";
|
||
|
my $path = <$repository>;
|
||
|
close $repository;
|
||
|
|
||
|
my($project) = $path =~ m{^([^/]+)};
|
||
|
chomp $project;
|
||
|
print STDERR "Testing '$project'\n";
|
||
|
|
||
|
|
||
|
use Getopt::Long;
|
||
|
|
||
|
my %Opts = ();
|
||
|
GetOptions(\%Opts, 'd', 'verbose');
|
||
|
|
||
|
my $Verbose = $ENV{HARNESS_VERBOSE} || $Opts{verbose};
|
||
|
|
||
|
my @names = @ARGV;
|
||
|
my @files = map File::Spec->rel2abs($_), @ARGV;
|
||
|
|
||
|
|
||
|
# Go to the top of the project.
|
||
|
chomp $path;
|
||
|
my $updir = join '/', ('..') x $path =~ tr|/||;
|
||
|
chdir $updir if length $updir;
|
||
|
|
||
|
my $test_dir = 'root/etc/e-smith/tests';
|
||
|
die "Can't find $test_dir" unless -d $test_dir;
|
||
|
|
||
|
chdir $test_dir;
|
||
|
@files = map File::Spec->abs2rel($_), @files;
|
||
|
|
||
|
|
||
|
# Use any libraries in this CVS repository. Test::Harness will
|
||
|
# automatically apply this to the tests.
|
||
|
our $This_Lib =
|
||
|
File::Spec->rel2abs('../../../../root/usr/lib/perl5/site_perl');
|
||
|
unshift @INC, $This_Lib;
|
||
|
|
||
|
|
||
|
if($Opts{d}) { # debugging
|
||
|
die "I need a file to debug.\n" unless @files;
|
||
|
die "You can only debug a single program at a time.\n" unless @files == 1;
|
||
|
|
||
|
my $file = $files[0];
|
||
|
my $name = $names[0];
|
||
|
warn "Debugging $file\n";
|
||
|
my $test_file = _test_file($file);
|
||
|
die "There are no tests in $name\n" unless $test_file;
|
||
|
system("PERL5LIB=$This_Lib $^X -d $test_file");
|
||
|
exit;
|
||
|
}
|
||
|
|
||
|
unless( @files ) {
|
||
|
find(sub {
|
||
|
if( -d $_ and $_ eq 'CVS' ) {
|
||
|
$File::Find::prune = 1;
|
||
|
return;
|
||
|
}
|
||
|
return if /~$/ || /^\.#/;
|
||
|
push @files, $File::Find::name if -f $_
|
||
|
}, '../../../..'
|
||
|
);
|
||
|
|
||
|
@names = map { (my $name = $_) =~ s[(\.\./){4}root/][]g; $name } @files;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
package My::Strap;
|
||
|
use Test::Harness::Straps;
|
||
|
our @ISA = qw(Test::Harness::Straps);
|
||
|
|
||
|
sub _display {
|
||
|
my($self, $out) = @_;
|
||
|
print $self->{_ml}."$out";
|
||
|
}
|
||
|
|
||
|
sub _print {
|
||
|
my($self) = shift;
|
||
|
print @_;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
### This is using an experimental callback interface in
|
||
|
### Test::Harness::Straps so it can print out test results as they
|
||
|
### happen. As the interface is experimental, check the changelog
|
||
|
### before upgrading Test::Harness::Straps.
|
||
|
|
||
|
my $s = My::Strap->new;
|
||
|
|
||
|
my %handlers = (
|
||
|
bailout => sub {
|
||
|
my($self, $line, $type, $totals) = @_;
|
||
|
|
||
|
die sprintf "FAILED--Further testing stopped%s\n",
|
||
|
$self->{bailout_reason} ? ": $self->{bailout_reason}" : '';
|
||
|
},
|
||
|
test => sub {
|
||
|
my($self, $line, $type, $totals) = @_;
|
||
|
my $curr = $totals->{seen};
|
||
|
|
||
|
if( $totals->{details}[-1]{ok} ) {
|
||
|
$self->_display("ok $curr/$totals->{max}") unless $Verbose;
|
||
|
}
|
||
|
else {
|
||
|
$self->_display("NOK $curr") unless $Verbose;
|
||
|
}
|
||
|
|
||
|
if( $curr > $self->{'next'} ) {
|
||
|
$self->_print("Test output counter mismatch [test $curr]\n");
|
||
|
}
|
||
|
elsif( $curr < $self->{'next'} ) {
|
||
|
$self->_print("Confused test output: test $curr answered after ".
|
||
|
"test ", $self->{next} - 1, "\n");
|
||
|
# $self->{'next'} = $curr;
|
||
|
}
|
||
|
},
|
||
|
);
|
||
|
|
||
|
$s->{callback} = sub {
|
||
|
my($self, $line, $type, $totals) = @_;
|
||
|
print $line if $Verbose;
|
||
|
|
||
|
$handlers{$type}->($self, $line, $type, $totals) if $handlers{$type};
|
||
|
};
|
||
|
|
||
|
|
||
|
close STDIN; # else tests might hang waiting for input.
|
||
|
|
||
|
|
||
|
# Iterate through each test or file and run that test.
|
||
|
# Most of the code herein is for nice formatting.
|
||
|
my $all_passing = 1;
|
||
|
my $width = _leader_width(@names);
|
||
|
$width = 70 if $width > 70;
|
||
|
foreach my $idx (0..$#files) {
|
||
|
my($file, $name) = ($files[$idx], $names[$idx]);
|
||
|
my %result = ();
|
||
|
|
||
|
my $test_file = _test_file($file);
|
||
|
next unless $test_file;
|
||
|
|
||
|
my($leader, $ml) = _mk_leader($name, $width);
|
||
|
print $leader;
|
||
|
print "\n" if $Verbose;
|
||
|
$s->{_ml} = $ml;
|
||
|
|
||
|
local $ENV{HARNESS_PERL_SWITCHES} = '-w';
|
||
|
%result = $s->analyze_file($test_file);
|
||
|
|
||
|
$all_passing = 0 unless $result{passing};
|
||
|
$s->_display($result{passing} ? 'ok' : 'FAILED');
|
||
|
print "\n";
|
||
|
}
|
||
|
|
||
|
if( $all_passing ) {
|
||
|
print "All tests successful!\n"
|
||
|
}
|
||
|
else {
|
||
|
print "SOME TESTS FAILED!\n";
|
||
|
}
|
||
|
|
||
|
|
||
|
=begin private
|
||
|
|
||
|
=over 4
|
||
|
|
||
|
=item B<_test_file>
|
||
|
|
||
|
my $test_file = _test_file($file);
|
||
|
|
||
|
Determines this $file is a test or has embedded tests and generates
|
||
|
a runable $test_file based on this.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub _test_file {
|
||
|
my $file = shift;
|
||
|
|
||
|
my $test_file;
|
||
|
if( $file =~ /\.t$/ ) {
|
||
|
$test_file = $file;
|
||
|
}
|
||
|
elsif( system("pod2test '$file' > /tmp/embedded$$.t") == 0 ) {
|
||
|
$test_file = "/tmp/embedded$$.t";
|
||
|
}
|
||
|
|
||
|
return $test_file;
|
||
|
}
|
||
|
|
||
|
=item B<_mk_leader>
|
||
|
|
||
|
my($leader, $ml) = _mk_leader($test_file, $width);
|
||
|
|
||
|
Generates the 't/foo........' $leader for the given $test_file as well
|
||
|
as a similar version which will overwrite the current line (by use of
|
||
|
\r and such). $ml may be empty if Test::Harness doesn't think you're
|
||
|
on TTY.
|
||
|
|
||
|
The $width is the width of the "yada/blah.." string.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub _mk_leader {
|
||
|
my($te, $width) = @_;
|
||
|
chomp($te);
|
||
|
$te =~ s/\.\w+$/./;
|
||
|
|
||
|
if ($^O eq 'VMS') { $te =~ s/^.*\.t\./\[.t./s; }
|
||
|
my $blank = (' ' x 77);
|
||
|
my $leader = "$te" . '.' x ($width - length($te));
|
||
|
my $ml = "";
|
||
|
|
||
|
$ml = "\r$blank\r$leader"
|
||
|
if -t STDOUT and not $ENV{HARNESS_NOTTY} and not $ENV{HARNESS_VERBOSE};
|
||
|
|
||
|
return($leader, $ml);
|
||
|
}
|
||
|
|
||
|
=item B<_leader_width>
|
||
|
|
||
|
my($width) = _leader_width(@test_files);
|
||
|
|
||
|
Calculates how wide the leader should be based on the length of the
|
||
|
longest test name.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
sub _leader_width {
|
||
|
my $maxlen = 0;
|
||
|
my $maxsuflen = 0;
|
||
|
foreach (@_) {
|
||
|
my $suf = /\.(\w+)$/ ? $1 : '';
|
||
|
my $len = length;
|
||
|
my $suflen = length $suf;
|
||
|
$maxlen = $len if $len > $maxlen;
|
||
|
$maxsuflen = $suflen if $suflen > $maxsuflen;
|
||
|
}
|
||
|
# + 3 : we want three dots between the test name and the "ok"
|
||
|
return $maxlen + 3 - $maxsuflen;
|
||
|
}
|
||
|
|
||
|
=back
|
||
|
|
||
|
=end private
|
||
|
|
||
|
|