[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. 2.1.4-9-g53ac0ac



The following commit has been merged in the master branch:
commit d8109b7e5a0a8586ab70ba88e8f976f6314eae1c
Author: Russ Allbery <rra@debian.org>
Date:   Sat Jan 10 18:47:06 2009 -0800

    Add checks for the layout of the binary package ar archive
    
    * checks/deb-format{,.desc}:
      + [RA] New check for the format of *.deb ar archives.  Most cases will
        fail during unpack, but dpkg-deb is more forgiving than dak and
        allows ordering problems and extra members that dak rejects.
        (Closes: #292055)
    * man/lintian.1:
      + [RA] Document new deb-format check script.
    * t/runtests:
      + [RA] Add support for building a Debian package using basic tools,
        with more complete control over the contents, and running lintian on
        the results.
    
    Also fix some problems with the changes test suite when running tests for
    a particular tag.

diff --git a/checks/deb-format b/checks/deb-format
new file mode 100644
index 0000000..ff950ee
--- /dev/null
+++ b/checks/deb-format
@@ -0,0 +1,85 @@
+# deb-format -- lintian check script -*- perl -*-
+
+# Copyright (C) 2009 Russ Allbery
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+package Lintian::deb_format;
+use strict;
+use Tags;
+
+use Lintian::Command qw(spawn);
+
+sub run {
+
+my $pkg = shift;
+my $type = shift;
+my $info = shift;
+
+# Run ar t on the *.deb file.  deb will be a symlink to it.
+my $okay = 0;
+my $opts = {};
+my $success = spawn($opts, ['ar', 't', 'deb']);
+if ($success) {
+    my @members = split("\n", ${ $opts->{out} });
+    if (@members != 3) {
+        my $count = scalar(@members);
+        tag 'malformed-deb-archive',
+            "found $count members instead of 3";
+    } elsif ($members[0] ne 'debian-binary') {
+        tag 'malformed-deb-archive',
+            "first member $members[0] not debian-binary";
+    } elsif ($members[1] ne 'control.tar.gz') {
+        tag 'malformed-deb-archive',
+            "second member $members[1] not control.tar.gz";
+    } elsif ($members[2] !~ /^data\.tar\.(gz|bz2)\z/) {
+        tag 'malformed-deb-archive',
+            "third member $members[2] not data.tar.(gz|bz2)";
+    } else {
+        $okay = 1;
+    }
+} else {
+    # unpack will probably fail so we'll never get here, but may as well be
+    # complete just in case.
+    my $error = ${ $opts->{err} };
+    $error =~ s/\n.*//s;
+    $error =~ s/^ar:\s*//;
+    $error =~ s/^deb:\s*//;
+    tag 'malformed-deb-archive', "ar error: $error";
+}
+
+# Check the debian-binary version number.  We probably won't get here because
+# dpkg-deb will decline to unpack the deb, but be thorough just in case.  We
+# may eventually have a case where dpkg supports a newer format but it's not
+# permitted in the archive yet.
+if ($okay) {
+    my $opts = {};
+    my $success = spawn($opts, ['ar', 'p', 'deb', 'debian-binary']);
+    if (not $success) {
+        tag 'malformed-deb-archive', "can't read debian-binary member";
+    } elsif (${ $opts->{out} } !~ /^2\.\d+\n/) {
+        my ($version) = split("\n", ${ $opts->{out} });
+        tag 'malformed-deb-archive', "version $version not 2.0";
+    }
+}
+
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 ts=4 et shiftround
diff --git a/checks/deb-format.desc b/checks/deb-format.desc
new file mode 100644
index 0000000..39f84af
--- /dev/null
+++ b/checks/deb-format.desc
@@ -0,0 +1,17 @@
+Check-Script: deb-format
+Author: Russ Allbery <rra@debian.org>
+Abbrev: dfmt
+Type: binary, udeb
+Unpack-Level: 1
+Info: This script checks the format of the deb ar archive itself.
+
+Tag: malformed-deb-archive
+Severity: serious
+Certainty: certain
+Info: The binary package is not a correctly constructed archive.  A binary
+ Debian package must be an ar archive with exactly three members:
+ <tt>debian-control</tt>, <tt>control.tar.gz</tt>, and
+ <tt>data.tar.gz</tt> or <tt>data.tar.bz2</tt> in exactly that order.  The
+ <tt>debian-control</tt> member must start with a single line containing
+ the version number, with a major revision of 2.
+Ref: deb(5)
diff --git a/debian/changelog b/debian/changelog
index d49044a..65a7105 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,10 +9,16 @@ lintian (2.1.5) UNRELEASED; urgency=low
       - changed-by-name-missing
       - duplicate-long-description
       - duplicate-short-description
+      - malformed-deb-archive
 
   * checks/control-file{,.desc}:
     + [RA] Tag (severity: wishlist) duplicate short or long descriptions
       in packages built from the same source.  (Closes: #30020)
+  * checks/deb-format{,.desc}:
+    + [RA] New check for the format of *.deb ar archives.  Most cases will
+      fail during unpack, but dpkg-deb is more forgiving than dak and
+      allows ordering problems and extra members that dak rejects.
+      (Closes: #292055)
   * checks/fields:
     + [RA] Use check_maintainer from Lintian::Check, which suppresses
       duplicate tags for some ill-formed maintainer fields.
@@ -31,9 +37,15 @@ lintian (2.1.5) UNRELEASED; urgency=low
   * lib/Lintian/Check.pm:
     + [RA] New module for checks run from multiple places.
 
+  * man/lintian.1:
+    + [RA] Document new deb-format check script.
+
   * t/runtests:
     + [RA] Add support for running lintian on changes files in t/changes
       and checking the tag output.
+    + [RA] Add support for building a Debian package using basic tools,
+      with more complete control over the contents, and running lintian on
+      the results.
     + [RA] Fix exit status when a test fails but -k was given.
 
  -- Russ Allbery <rra@debian.org>  Mon, 05 Jan 2009 10:41:18 -0800
diff --git a/man/lintian.1 b/man/lintian.1
index 90a20b1..3628a73 100644
--- a/man/lintian.1
+++ b/man/lintian.1
@@ -428,6 +428,10 @@ Looks for cruft in source packages, like files of version control
 systems and temporary files from the build process.
 
 .TP
+.B deb-format (dfmt)
+Checks the format of the binary package ar archive.
+
+.TP
 .B debconf (dc)
 Looks for common mistakes in packages using debconf, like missing
 dependencies or errors in the template file.
diff --git a/private/update-coverage b/private/update-coverage
index 7f72f36..1d6bdd6 100755
--- a/private/update-coverage
+++ b/private/update-coverage
@@ -59,8 +59,8 @@ for my $desc (<t/tests/*.desc>) {
     }
 }
 
-# Parse all tags files for the changes test suite.
-for my $tagfile (<t/changes/*.tags>) {
+# Parse all tags files for the changes and debs test suite.
+for my $tagfile (<t/changes/*.tags> <t/debs/*/tags) {
     open(IN, '<', $tagfile) or die "Cannot open $tagfile: $!\n";
     local $_;
     while (<IN>) {
diff --git a/t/debs/README b/t/debs/README
new file mode 100644
index 0000000..095d87c
--- /dev/null
+++ b/t/debs/README
@@ -0,0 +1,99 @@
+WRITING A TEST
+==============
+
+This test framework is intended to test low-level Lintian checks
+and behavior with very malformed packages.  It provides a mechanism
+to manually construct pathological deb files and run lintian on
+them.  It should only be used when this degree of low-level control
+is necessary.  For other, more conventional cases, use the tests
+framework.
+
+A test in this framework is a directory containing (at least) a tags
+file and a Makefile.  The directory may contain other files as needed
+for that test.
+
+The tags file
+-------------
+
+The expected output of Lintian when run on the package, including info
+and experimental tags.  The Lintian output will be lexicographically
+sorted before comparing it with tags.  This file may be empty if the
+test case should produce no Lintian output.
+
+The Makefile
+------------
+
+Makefile must be a GNU makefile which, when invoked via make (using
+the default target), creates a <testname>.deb file in the current
+directory.  <testname> must match the directory name.  This makefile
+may assume that the current working directory when it is invoked is
+the directory in which it's located (or a copy of it).  It can take
+any action needed to generate the deb file, such as running dpkg-deb
+or ar.
+
+The Makefile does not have to clean up after itself.  It can assume
+that the directory is deleted and recreated between test runs.
+
+The packages are constructed using fakeroot, so the Makefile doesn't
+need to worry about file ownership when creating the files as long
+as all files included in the archive are newly created or chowned
+before creating the deb.
+
+
+TEST NAMING CONVENTIONS
+=======================
+
+Each test name should begin with the name of the part tested, e.g.
+
+<checkname>-...
+<unpackname>-...
+lintian-...
+lintian-info-...
+
+Use generic- as a prefix for test cases that don't cover a specific
+portion of Lintian but instead test Lintian's behavior on a useful
+special case of package (such as a minimal package).
+
+
+RUNNING THE TEST SUITE
+======================
+
+The complete test suite will be run with debian/rules runtests, but
+this can take quite a lot of time.  Normally this is only necessary
+after significant structural changes or before a release as a final
+check.
+
+To run a specific test case, run:
+
+    debian/rules runtests onlyrun=<desc-name>
+
+You can omit the .desc from the end of <desc-name>, but you need to
+include the leading sequence number and underscore.  Give only the
+file name, not the full path.
+
+It's often more useful to run every test that is relevant to a
+particular tag.  To do that, run:
+
+    debian/rules check-tag tag=<tag>
+
+This will run all tests that list that tag in the tags file.
+
+
+TEST WRITING TIPS
+=================
+
+Please keep each test case focused.  One of the problems that
+developed with the old test suite is that each test was serving many
+separate purposes and testing large swaths of Lintian, which made it
+difficult to know what could be changed and what would destroy some
+other useful test.  Test cases should only test a set of closely
+related tags and new tests should be added for new issues that aren't
+part of that closely-related set.
+
+Test cases should be as Lintian-clean as possible except for the tags
+that they're testing for.  The template is intended to help with this.
+It generates a Lintian-clean basic package for you to start with.  You
+should override only the minimal required to trigger your test, and
+try to fix any unrelated problems.  Sometimes this won't be possible
+and the only way to trigger a tag is to also trigger another tag, and
+that's fine, but it shouldn't be the normal case.
diff --git a/t/debs/deb-format-extra-member/Makefile b/t/debs/deb-format-extra-member/Makefile
new file mode 100644
index 0000000..9159288
--- /dev/null
+++ b/t/debs/deb-format-extra-member/Makefile
@@ -0,0 +1,17 @@
+all:
+	echo '2.0' > debian-binary
+	echo 'foo' > extra-stuff
+	mkdir -p usr/share/doc/deb-format-extra-member
+	cp copyright changelog usr/share/doc/deb-format-extra-member
+	gzip -9 usr/share/doc/deb-format-extra-member/changelog
+	tar cfz data.tar.gz usr
+	chown 0:0 control
+	chmod 644 control
+	md5sum usr/share/doc/deb-format-extra-member/* > md5sums
+	tar cfz control.tar.gz control md5sums
+	ar rc deb-format-extra-member.deb \
+	    debian-binary control.tar.gz data.tar.gz extra-stuff
+
+clean:
+	rm -f *.tar.gz *.deb md5sums debian-binary extra-stuff
+	rm -rf usr
diff --git a/t/debs/deb-format-extra-member/changelog b/t/debs/deb-format-extra-member/changelog
new file mode 100644
index 0000000..00205ac
--- /dev/null
+++ b/t/debs/deb-format-extra-member/changelog
@@ -0,0 +1,5 @@
+deb-format-wrong-order (1.0) unstable; urgency=low
+
+  * A Lintian test case.
+
+ -- Debian Lintian Maintainers <lintian-maint@debian.org>  Thu, 01 Jan 2009 08:34:20 -0800
diff --git a/testset/diffs/debian/control b/t/debs/deb-format-extra-member/control
similarity index 51%
copy from testset/diffs/debian/control
copy to t/debs/deb-format-extra-member/control
index 3ea2504..23e33a5 100644
--- a/testset/diffs/debian/control
+++ b/t/debs/deb-format-extra-member/control
@@ -1,14 +1,10 @@
-Source: diffs
-Section: interpreters
-Priority: extra
-Maintainer: Lintian Maintainers <lintian-maint@debian.org>
-Build-Depends: dpatch
-Standards-Version: 3.5.9
-
-Package: diffs
+Package: deb-format-extra-member
+Version: 1.0
 Architecture: all
-Depends: test
-Description: test lintian's diff file checks
+Maintainer: Debian Lintian Maintainers <lintian-maint@debian.org>
+Section: devel
+Priority: extra
+Description: Test package for an ar archive in the wrong order
  This is a test package designed to exercise some feature or tag of
  Lintian.  It is part of the Lintian test suite and may do very odd
  things.  It should not be installed like a regular package.
diff --git a/t/templates/skel/debian/copyright b/t/debs/deb-format-extra-member/copyright
similarity index 88%
copy from t/templates/skel/debian/copyright
copy to t/debs/deb-format-extra-member/copyright
index b780d82..98298fd 100644
--- a/t/templates/skel/debian/copyright
+++ b/t/debs/deb-format-extra-member/copyright
@@ -1,8 +1,8 @@
 This is part of the testsuite of lintian. See the file debian/copyright
 in the lintian source directory for more details.
 
-So far as it is copyrightable at all, this template is
-   Copyright © 2008 Frank Lichtenheld <djpig@debian.org>
+So far as it is copyrightable at all, this test case is
+   Copyright © 2009 Russ Allbery <rra@debian.org>
 
 This program is free software; you may redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/t/debs/deb-format-extra-member/tags b/t/debs/deb-format-extra-member/tags
new file mode 100644
index 0000000..6e19acf
--- /dev/null
+++ b/t/debs/deb-format-extra-member/tags
@@ -0,0 +1 @@
+E: deb-format-extra-member: malformed-deb-archive found 4 members instead of 3
diff --git a/t/debs/deb-format-wrong-order/Makefile b/t/debs/deb-format-wrong-order/Makefile
new file mode 100644
index 0000000..fa0ccdd
--- /dev/null
+++ b/t/debs/deb-format-wrong-order/Makefile
@@ -0,0 +1,16 @@
+all:
+	echo '2.0' > debian-binary
+	mkdir -p usr/share/doc/deb-format-wrong-order
+	cp copyright changelog usr/share/doc/deb-format-wrong-order
+	gzip -9 usr/share/doc/deb-format-wrong-order/changelog
+	tar cfz data.tar.gz usr
+	chown 0:0 control
+	chmod 644 control
+	md5sum usr/share/doc/deb-format-wrong-order/* > md5sums
+	tar cfz control.tar.gz control md5sums
+	ar rc deb-format-wrong-order.deb \
+	    debian-binary data.tar.gz control.tar.gz
+
+clean:
+	rm -f *.tar.gz *.deb md5sums debian-binary
+	rm -rf usr
diff --git a/t/debs/deb-format-wrong-order/changelog b/t/debs/deb-format-wrong-order/changelog
new file mode 100644
index 0000000..00205ac
--- /dev/null
+++ b/t/debs/deb-format-wrong-order/changelog
@@ -0,0 +1,5 @@
+deb-format-wrong-order (1.0) unstable; urgency=low
+
+  * A Lintian test case.
+
+ -- Debian Lintian Maintainers <lintian-maint@debian.org>  Thu, 01 Jan 2009 08:34:20 -0800
diff --git a/testset/diffs/debian/control b/t/debs/deb-format-wrong-order/control
similarity index 51%
copy from testset/diffs/debian/control
copy to t/debs/deb-format-wrong-order/control
index 3ea2504..fb980ab 100644
--- a/testset/diffs/debian/control
+++ b/t/debs/deb-format-wrong-order/control
@@ -1,14 +1,10 @@
-Source: diffs
-Section: interpreters
-Priority: extra
-Maintainer: Lintian Maintainers <lintian-maint@debian.org>
-Build-Depends: dpatch
-Standards-Version: 3.5.9
-
-Package: diffs
+Package: deb-format-wrong-order
+Version: 1.0
 Architecture: all
-Depends: test
-Description: test lintian's diff file checks
+Maintainer: Debian Lintian Maintainers <lintian-maint@debian.org>
+Section: devel
+Priority: extra
+Description: Test package for an ar archive in the wrong order
  This is a test package designed to exercise some feature or tag of
  Lintian.  It is part of the Lintian test suite and may do very odd
  things.  It should not be installed like a regular package.
diff --git a/t/templates/skel/debian/copyright b/t/debs/deb-format-wrong-order/copyright
similarity index 88%
copy from t/templates/skel/debian/copyright
copy to t/debs/deb-format-wrong-order/copyright
index b780d82..98298fd 100644
--- a/t/templates/skel/debian/copyright
+++ b/t/debs/deb-format-wrong-order/copyright
@@ -1,8 +1,8 @@
 This is part of the testsuite of lintian. See the file debian/copyright
 in the lintian source directory for more details.
 
-So far as it is copyrightable at all, this template is
-   Copyright © 2008 Frank Lichtenheld <djpig@debian.org>
+So far as it is copyrightable at all, this test case is
+   Copyright © 2009 Russ Allbery <rra@debian.org>
 
 This program is free software; you may redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/t/debs/deb-format-wrong-order/tags b/t/debs/deb-format-wrong-order/tags
new file mode 100644
index 0000000..aafecf5
--- /dev/null
+++ b/t/debs/deb-format-wrong-order/tags
@@ -0,0 +1 @@
+E: deb-format-wrong-order: malformed-deb-archive second member data.tar.gz not control.tar.gz
diff --git a/t/runtests b/t/runtests
index d030aaf..576adf1 100755
--- a/t/runtests
+++ b/t/runtests
@@ -156,8 +156,48 @@ for (@tests) {
     $tests_run++;
 }
 
+# --- Run all debs tests
+
+my $prev = scalar(@tests);
+@tests = ();
+if ($singletest) {
+    my $test = $singletest;
+    if (-d "$TESTSET/debs/$test") {
+	@tests = ($test);
+    }
+} elsif ($tag) {
+    @tests = find_debs_for_tag($tag);
+} else {
+    unless (-d "$TESTSET/debs") {
+	fail("cannot find $TESTSET/debs: $!");
+    }
+    @tests = map {
+	if (-d $_) {
+	    s,^\Q$TESTSET/debs/\E,,;
+	    $_;
+	} else {
+	    ();
+	}
+    } sort(<$TESTSET/debs/*>);
+}
+if ($prev and @tests) {
+    print "\n";
+    $prev = 0;
+}
+print "Found the following debs tests: @tests\n" if $DEBUG;
+print "Raw Debian package tests:\n" if @tests;
+for (@tests) {
+    my $okay = test_deb($_);
+    unless ($okay) {
+	exit 1 unless $run_all_tests;
+	$status = 1;
+    }
+    $tests_run++;
+}
+
 # --- Run all package tests
 
+$prev = $prev || scalar(@tests);
 @tests = ();
 if ($singletest) {
     my $test = $singletest;
@@ -177,7 +217,7 @@ if ($singletest) {
 	$_;
     } sort(<$TESTSET/tests/*.desc>);
 }
-print "\n" if ($tests_run and @tests);
+print "\n" if ($prev and @tests);
 print "Found the following tests: @tests\n" if $DEBUG;
 print "Package tests:\n" if @tests;
 for (@tests) {
@@ -356,7 +396,7 @@ sub test_package {
 sub find_changes_for_tag {
     my ($tag) = @_;
     my @tests;
-    for my $test (<$TESTSET/*.tags>) {
+    for my $test (<$TESTSET/changes/*.tags>) {
 	my ($testname) = ($test =~ m,.*/([^/]+)\.tags$,);
 	open(TAGS, '<', $test) or fail("Cannot open $test");
 	local $_;
@@ -365,8 +405,12 @@ sub find_changes_for_tag {
 	    if (not /^.: \S+(?: (?:source|udeb))?: (\S+)/) {
 		next;
 	    }
+	    if ($1 eq $tag) {
+		push(@tests, $testname);
+		last;
+	    }
 	}
-	push(@tests, $1);
+	close TAGS;
     }
     return @tests;
 }
@@ -398,6 +442,66 @@ sub test_changes {
     }
 }
 
+# --- Raw Debian package testing
+
+# Find all debs tests that check a particular tag, either for its presence
+# or absence.  Returns a list of check names.
+sub find_debs_for_tag {
+    my ($tag) = @_;
+    my @tests;
+    for my $test (<$TESTSET/debs/*/tags>) {
+	my ($testname) = ($test =~ m,.*/([^/]+)/tags$,);
+	open(TAGS, '<', $test) or fail("Cannot open $test");
+	local $_;
+	while (<TAGS>) {
+	    next if /^N: /;
+	    if (not /^.: \S+(?: (?:source|udeb))?: (\S+)/) {
+		next;
+	    }
+	    if ($1 eq $tag) {
+		push(@tests, $testname);
+		last;
+	    }
+	}
+	close TAGS;
+    }
+    return @tests;
+}
+
+# Run a test on a changes file and show any diffs in the expected tags or any
+# other errors detected.  Takes the test name.  Returns true if the test
+# passes and false if it fails.
+sub test_deb {
+    my ($test) = @_;
+    print "Running test $test... ";
+
+    my $testdir = "$TESTSET/debs/$test";
+    my $targetdir = "$RUNDIR/$test";
+
+    print "Cleaning up and repopulating $targetdir...\n" if $DEBUG;
+    runsystem_ok("rm", "-rf", $targetdir);
+    runsystem("cp", "-rp", $testdir, $targetdir);
+
+    print "building... ";
+    runsystem("cd $targetdir && fakeroot make >../build.$test 2>&1");
+
+    print "testing... ";
+    runsystem_ok("$LINTIAN $targetdir/$test.deb 2>&1" .
+		 " | sort > $RUNDIR/tags.$test");
+
+    # Compare the output to the expected tags.
+    my $testok = runsystem_ok('cmp', '-s', "$testdir/tags",
+			      "$RUNDIR/tags.$test");
+    if ($testok) {
+	print "ok.\n";
+	return 1;
+    } else {
+	print "FAILED:\n";
+	runsystem_ok("diff", "-u", "$testdir/tags", "$RUNDIR/tags.$test");
+	return;
+    }
+}
+
 # --------------
 
 # Unquote a heredoc, used to make them a bit more readable in Perl code.

-- 
Debian package checker


Reply to: