#!/usr/bin/perl -w # Copyright (C) 1998 Richard Braakman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, you can find it on the World Wide # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. use strict; sub usage { print <= 0 && $ARGV[0] =~ m/^-/) { if ($ARGV[0] eq '-k') { $run_all_tests = 1; } elsif ($ARGV[0] eq '-v') { $verbose = 1; } elsif ($ARGV[0] eq '-d') { $debug = 1; } else { usage; } shift; } # --- Parse directory arguments if ($#ARGV < 1 || $#ARGV > 2) { usage; } my $testset = shift; my $rundir = shift; my $singletest; if ($#ARGV == 0) { $singletest = shift; } # --- Set and unset environment variables that lintian is sensitive to BEGIN { my $LINTIAN_ROOT = $ENV{'LINTIAN_ROOT'}; if (not $LINTIAN_ROOT) { use Cwd (); $ENV{'LINTIAN_ROOT'} = $LINTIAN_ROOT = Cwd::cwd(); } delete $ENV{'LINTIAN_CFG'}; delete $ENV{'LINTIAN_LAB'}; delete $ENV{'LINTIAN_DIST'}; delete $ENV{'LINTIAN_UNPACK_LEVEL'}; $ENV{'LC_COLLATE'} = 'C'; # Set standard umask because many of the test packages rely on this # when creating files from the debian/rules script. umask(022); } my $LINTIAN_ROOT = $ENV{'LINTIAN_ROOT'}; use lib "$ENV{'LINTIAN_ROOT'}/lib"; use Lintian::Profile; use Util; # --- Set the ways to call lintian and dpkg-buildpackage my $lintian_options = '-I -E'; my $lintian_info_options = '-I -E -i'; my $dpkg_buildpackage_options = '-rfakeroot -us -uc -d -iNEVER_MATCH_ANYTHING' . ' -INEVER_MATCH_ANYTHING'; my $lintian_path = $LINTIAN_ROOT . "/frontend/lintian"; my $testok = 0; my %tags; # --- Display output immediately $| = 1; # --- Let's play. -d $rundir or fail("test directory $rundir does not exist\n"); $testok = 1; my $profile = Lintian::Profile->new ('debian/main', $ENV{'LINTIAN_ROOT'}, ["$ENV{'LINTIAN_ROOT'}/profiles"]); # force all checks to be loaded - not the best solution # - At the time of writing it is not needed for 'debian/main', but # that may change... $profile->_load_checks(); for my $tag ($profile->tags (1)){ my $ti = $profile->get_tag ($tag, 1); my $code = $ti->code; $code = 'X' if $ti->experimental; $tags{$tag}{'desc_file'} = $ti->script .'.desc'; $tags{$tag}{'desc_type'} = $code; } undef $profile; # Don't need it any more. if ($testok) { print "done.\n"; } else { print "FAILED!\n"; exit 1 unless $run_all_tests; } # ok, I can make a static lab, now let's test the package checks # in temporary labs my @tests; if ($singletest) { @tests = ( $singletest ); } else { opendir(TESTDIR, $testset) or fail("cannot open $testset: $!\n"); @tests = sort(readdir(TESTDIR)); closedir(TESTDIR); } my $tests_run = 0; for (@tests) { next if $_ eq '.' or $_ eq '..' or $_ eq 'CVS' or $_ eq '.svn'; next unless -d "$testset/$_"; my $pkgdir = $_; open(CHANGELOG, "$testset/$pkgdir/debian/changelog") or die("Could not open $testset/$pkgdir/debian/changelog"); my $line = ; chomp($line); close(CHANGELOG); $line =~ s/^.*\(//; $line =~ s/\).*$//; my ($pkg, $ver) = ($pkgdir, $line); $ver =~ s/(^|-)\d+:/$1/; print "Running test on $pkg $ver: copying... "; print "Cleaning up and repopulating $rundir/$pkgdir...\n" if $debug; runsystem_ok("rm -rf $rundir/$pkgdir"); runsystem("cp -rp $testset/$pkgdir $rundir"); opendir D, "$testset" or die; foreach (readdir D) { next unless /^\Q${pkg}\E_.*\.orig\.tar\.gz$/; print "Symlinking $_ in $rundir...\n" if $debug; symlink $ENV{'PWD'}."/$testset/$_", "$rundir/$_"; } closedir D; runsystem("find $rundir -name CVS -o -name .svn -print0 | xargs -0r rm -R"); print "building... "; print "Running dpkg-buildpackage $dpkg_buildpackage_options in $rundir/$pkgdir...\n" if $debug; runsystem("cd $rundir/$pkgdir && dpkg-buildpackage $dpkg_buildpackage_options >../build.$pkg 2>&1"); print "testing... "; print "Running lintian --allow-root --no-cfg $lintian_options on $rundir/$pkg\_$ver*.changes...\n" if $debug; runsystem_ok("$lintian_path --allow-root --no-cfg $lintian_options $rundir/$pkg\_$ver*.changes". " 2>&1 | sort > $rundir/tags.$pkg"); # Run a sed-script if it exists, for tests that have slightly variable # output runsystem_ok("sed -i -f $testset/tags.$pkg.sed $rundir/tags.$pkg") if -e "$testset/tags.$pkg.sed"; $testok = runsystem_ok("cmp -s $rundir/tags.$pkg $testset/tags.$pkg"); $tests_run++; if ($testok) { print "done.\n"; } else { print "FAILED:\n"; runsystem_ok("diff -u $testset/tags.$pkg $rundir/tags.$pkg"); exit 1 unless $run_all_tests; next; } open TAGS, "$rundir/tags.$pkg" or fail("Cannot open $rundir/tags.$pkg"); while () { next if m/^N: /; if (not /^(.): (\S+)(?: (?:source|udeb|changes))?: (\S+)/) { print "E: Invalid line:\n$_"; next; } $tags{$3}{'tested_type'} = $1; $tags{$3}{'tested_package'} = $2; } close TAGS; } if (!$tests_run) { if ($singletest) { print "W: No tests run, did you specify a valid test name?\n"; } else { print "E: No tests run, did you specify a valid testset directory?\n"; } } print "Checking whether all tags are tested and tags have description ... \n"; $testok = 1; for (keys %tags) { my $values = $tags{$_}; if (not defined $values->{'desc_type'}) { print "E: tag-has-no-description $_ in $values->{'tested_package'}\n"; $testok = 0; } elsif (not defined $values->{'tested_type'}) { print "I: tag-is-not-tested $_ in $values->{'desc_file'}\n" if $verbose; } elsif ($values->{'desc_type'} ne $values->{'tested_type'}) { print "E: tag-has-inconsistent-type $_ $values->{'tested_type'} vs ". "$values->{'desc_type'}\n"; $testok = 0; } } if ($testok) { print "done.\n"; } else { print "FAILED\n"; exit 1 unless $run_all_tests; } # -------------- sub runsystem { system(@_) == 0 or fail("failed: @_\n"); } sub runsystem_ok { my $errcode = system(@_); $errcode == 0 or $errcode == (1 << 8) or fail("failed: @_\n"); return $errcode == 0; } # Local Variables: # indent-tabs-mode: nil # cperl-indent-level: 4 # End: # vim: syntax=perl sw=4 sts=4 sr et