#!/usr/bin/perl -w # Usage: # pc_script_test [dir1 [dir2 [...]]] # # Description: # Run tests in tests/ directories. These are normally tests of # Python or IDL scripts, or similar. # For each directory given, we recursively scan for subdirectories # named 'tests'. If no directories are given, the directories # tests/, samples/, runs/ of ${PENCIL_HOME} are used as starting # points. # # Under each tests/ directory, we look for test files (which may be # located deeper in subdirectories). # The contract for a test file: # - It is named ., where is a known suffix # - (currently supported: py, pro). # - The file is executable and can be run from the tests directory # (thus, many of the test scripts read data from '../data/'). # - When run, the script writes a file .out in the same # directory. # - There exist a file .ref in the same directory that defines # the reference data and possibly accuracy. # # Each test script is run (if we find an appropriate interpreter) # and the .out file is compared to the reference data # .ref . # # Examples: # pc_script_test # Run all tests under $PENCIL_HOME/{tests,samples,runs}/ # pc_script_test # Run all tests under the given directory # # TODO: # - scan directories for 'test' # - find test files # - for each test file: # - cd to its directory # - run it # - compare .ref and .out files # - [should we allow the case where no .ref exists and no .out is written?] # - Give some output [spinner or '.', or ...] # - summarize results use strict; BEGIN { # Make sure ${PENCIL_HOME}/lib/perl is in the Perl path if (-d "$ENV{PENCIL_HOME}/lib/perl") { unshift @INC, "$ENV{PENCIL_HOME}/lib/perl"; } else { if ($0 =~ m!(.*[/\\])!) { unshift @INC, "$1../lib/perl"; } } } use Pencil::Util; Pencil::Util::use_pencil_perl_modules('Test::ScriptTester') or die; use Getopt::Long; # Allow for `-Plp' as equivalent to `-P lp' etc: Getopt::Long::config("bundling"); my %opts; # Options hash for GetOptions ## Process command line GetOptions(\%opts, qw( -h --help -t=s --type=s --debug -q --quiet -v --version ) ) or die "Aborting.\n"; my $debug = ($opts{'debug'} ? 1 : 0 ); # undocumented debug option if ($debug) { printopts(\%opts); print "\@ARGV = `@ARGV'\n"; } my $cmdname = (split('/', $0))[-1]; if ($opts{'h'} || $opts{'help'}) { die usage(); } if ($opts{'v'} || $opts{'version'}) { die version(); } my $default_types = "python:idl"; my @types = split(/:/, $opts{'t'} || $opts{'type'} || $default_types); my $quiet = $opts{'q'} || $opts{'quiet'} || ''; my %run_dispatch_table = ( python => \&run_python_script, idl => \&run_idl_script, ); my @default_dirs = ( "$ENV{PENCIL_HOME}/tests", "$ENV{PENCIL_HOME}/samples", "$ENV{PENCIL_HOME}/runs", ); my @top_dirs = @ARGV ? @ARGV : @default_dirs; my $tester = Test::ScriptTester->new(\@top_dirs); my ($good_count, $bad_count) = $tester->run(); my $separator = ('-' x 70) . "\n"; print "$separator"; my $total_count = $good_count + $bad_count; if ($bad_count) { print "$bad_count out of $total_count tests failed.\n"; } else { print "All $total_count tests succeeded.\n"; } print "$separator"; exit $bad_count; sub debug { my @args = @_; if ($debug) { my $string = join(' ', @args); chomp($string); print "$string\n"; } } sub printopts { # Print command line options my ($optsref) = @_; my %opts = %$optsref; foreach my $opt (keys(%opts)) { print STDERR "\$opts{$opt} = '$opts{$opt}'\n"; } } sub usage { # Extract description and usage information from this file's header. my $thisfile = __FILE__; local $/ = ''; # Read paragraphs open my $fh, '<', $thisfile or die "Cannot open $thisfile\n"; while (<$fh>) { # Paragraph _must_ contain `Description:' or `Usage:' next unless /^ \s* \# \s* ( Description | Usage ) : /mx; # Drop `Author:', etc. (anything before `Description:' or `Usage:') s/^ (?: .*? \n) ?? ( \s* \# \s* (?: Description | Usage ) : \s* \n .* ) / $1 /sx; # Don't print comment sign: s/^\s*# ?//mg; last; # ignore body } close $fh; return $_ or "\n"; } sub version { # Return SVN/CVS data and version info. my $doll='\$'; # Need this to trick SVN/CVS my $rev = '$Revision: 1.12 $'; my $date = '$Date: 2008/07/07 21:37:16 $'; $rev =~ s/${doll}Revision:\s*(\S+).*/$1/; $date =~ s/${doll}Date:\s*(\S+).*/$1/; return "$cmdname version $rev ($date)\n"; }