summaryrefslogtreecommitdiffstats
path: root/test/test_mergechanges
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_mergechanges')
-rwxr-xr-xtest/test_mergechanges551
1 files changed, 551 insertions, 0 deletions
diff --git a/test/test_mergechanges b/test/test_mergechanges
new file mode 100755
index 0000000..e689cd7
--- /dev/null
+++ b/test/test_mergechanges
@@ -0,0 +1,551 @@
+#!/usr/bin/perl
+
+# Copyright 2019 Simon McVittie
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# 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 <https://www.gnu.org/licenses/>.
+
+use strict;
+use warnings;
+
+use Cwd qw(getcwd);
+use Data::Dumper;
+use File::Temp qw(tempdir);
+use IPC::Run qw(run);
+use Test::More;
+
+use Dpkg::Control;
+
+my $srcdir = getcwd;
+my $top_srcdir = getcwd . '/..';
+my $mergechanges = "$top_srcdir/scripts/mergechanges.sh";
+
+if (defined $ARGV[0] && $ARGV[0] eq '--installed') {
+ $mergechanges = 'mergechanges';
+}
+
+my $tmp = tempdir(CLEANUP => 1);
+my $stdout;
+my $stderr;
+my $fh;
+my $merged;
+my $all = 'xdg-desktop-portal_1.2.0-1_all.changes';
+my $amd64 = 'xdg-desktop-portal_1.2.0-1_amd64.changes';
+my $source = 'xdg-desktop-portal_1.2.0-1_source.changes';
+my %controls;
+my @words;
+my @lines;
+my $orig;
+
+sub verbose_run {
+ my $argv = shift;
+ diag("Running: @{$argv}");
+ return run($argv, @_);
+}
+
+sub capture {
+ my $output;
+ my $argv = shift;
+ ok(verbose_run($argv, '>', \$output), "@{$argv}");
+ chomp $output;
+ return $output;
+}
+
+sub uniq {
+ my %seen;
+ my @ret;
+ foreach my $member (@_) {
+ push @ret, $member unless defined $seen{$member};
+ $seen{$member} = 1;
+ }
+ return @ret;
+}
+
+sub verbose_is_deeply {
+ diag Dumper($_[0], $_[1]);
+ is_deeply(@_);
+}
+
+foreach my $name ($all, $amd64, $source) {
+ $controls{$name} = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+ $controls{$name}->load("mergechanges/$name");
+}
+
+diag('Help');
+$stdout = capture([
+ $mergechanges,
+ '--help',
+]);
+like($stdout, qr{Usage:});
+
+diag('Version');
+$stdout = capture([
+ $mergechanges,
+ '--version',
+]);
+like($stdout, qr{devscripts package});
+
+diag('Simple merge');
+$stdout = capture([
+ $mergechanges,
+ "mergechanges/$all",
+ "mergechanges/$amd64",
+ "mergechanges/$source",
+]);
+#diag $stdout;
+unlike($stdout, qr/BEGIN PGP/);
+unlike($stdout, qr/END PGP/);
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+open($fh, '<', \$stdout);
+$merged->parse($fh, 'stdout of mergechanges');
+close($fh);
+is($merged->{Format}, $controls{$source}->{Format});
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+@words = sort split / /, $merged->{Binary};
+is_deeply(\@words, [sort qw(
+ xdg-desktop-portal
+ xdg-desktop-portal-dbgsym
+ xdg-desktop-portal-dev
+ xdg-desktop-portal-tests
+ xdg-desktop-portal-tests-dbgsym
+)]);
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(amd64 all source)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Description}),
+ (split /\n/, $controls{$amd64}->{Description}),
+))]);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Files}),
+ (split /\n/, $controls{$amd64}->{Files}),
+ (split /\n/, $controls{$source}->{Files}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{'Checksums-Sha1'}),
+ (split /\n/, $controls{$amd64}->{'Checksums-Sha1'}),
+ (split /\n/, $controls{$source}->{'Checksums-Sha1'}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{'Checksums-Sha256'}),
+ (split /\n/, $controls{$amd64}->{'Checksums-Sha256'}),
+ (split /\n/, $controls{$source}->{'Checksums-Sha256'}),
+))]);
+
+diag('Source only');
+$stdout = capture([
+ $mergechanges,
+ '-S',
+ "mergechanges/$all",
+ "mergechanges/$amd64",
+ "mergechanges/$source",
+]);
+#diag $stdout;
+unlike($stdout, qr/BEGIN PGP/);
+unlike($stdout, qr/END PGP/);
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+open($fh, '<', \$stdout);
+$merged->parse($fh, 'stdout of mergechanges');
+close($fh);
+is($merged->{Format}, $controls{$source}->{Format});
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+is($merged->{Binary}, undef);
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(source)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+is($merged->{Description}, undef);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{Files}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha1'}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha256'}),
+))]);
+
+diag('Indep only');
+$stdout = capture([
+ $mergechanges,
+ '-i',
+ "mergechanges/$all",
+ "mergechanges/$amd64",
+ "mergechanges/$source",
+]);
+#diag $stdout;
+unlike($stdout, qr/BEGIN PGP/);
+unlike($stdout, qr/END PGP/);
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+open($fh, '<', \$stdout);
+$merged->parse($fh, 'stdout of mergechanges');
+close($fh);
+is($merged->{Format}, $controls{$source}->{Format});
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+is($merged->{Binary}, 'xdg-desktop-portal-dev');
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(all source)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Description}),
+))]);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{Files}),
+ (split /\n/, $controls{$all}->{Files}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha1'}),
+ (split /\n/, $controls{$all}->{'Checksums-Sha1'}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha256'}),
+ (split /\n/, $controls{$all}->{'Checksums-Sha256'}),
+))]);
+
+diag('To file');
+ok(run(['cp', "mergechanges/$source", "$tmp/source.changes"]));
+$stdout = capture([
+ $mergechanges,
+ '-f',
+ "$tmp/source.changes",
+ "mergechanges/$all",
+]);
+ok(-e "$tmp/source.changes");
+is($stdout, '');
+#system("cat", "$tmp/xdg-desktop-portal_1.2.0-1_multi.changes");
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+$merged->load("$tmp/xdg-desktop-portal_1.2.0-1_multi.changes");
+is($merged->{Format}, $controls{$source}->{Format});
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+is($merged->{Binary}, 'xdg-desktop-portal-dev');
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(all source)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Description}),
+))]);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{Files}),
+ (split /\n/, $controls{$all}->{Files}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha1'}),
+ (split /\n/, $controls{$all}->{'Checksums-Sha1'}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha256'}),
+ (split /\n/, $controls{$all}->{'Checksums-Sha256'}),
+))]);
+
+diag('Deleting');
+ok(run(['cp', "mergechanges/$source", "$tmp/source.changes"]));
+ok(run(['cp', "mergechanges/$all", "$tmp/all.changes"]));
+$stdout = capture([
+ $mergechanges,
+ '-d',
+ '-f',
+ "$tmp/source.changes",
+ "$tmp/all.changes",
+]);
+ok(! -e "$tmp/source.changes");
+ok(! -e "$tmp/all.changes");
+is($stdout, '');
+#system("cat", "$tmp/xdg-desktop-portal_1.2.0-1_multi.changes");
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+$merged->load("$tmp/xdg-desktop-portal_1.2.0-1_multi.changes");
+is($merged->{Format}, $controls{$source}->{Format});
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+is($merged->{Binary}, 'xdg-desktop-portal-dev');
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(all source)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Description}),
+))]);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{Files}),
+ (split /\n/, $controls{$all}->{Files}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha1'}),
+ (split /\n/, $controls{$all}->{'Checksums-Sha1'}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$source}->{'Checksums-Sha256'}),
+ (split /\n/, $controls{$all}->{'Checksums-Sha256'}),
+))]);
+
+diag('Merge with itself');
+$stdout = capture([
+ $mergechanges,
+ '--indep',
+ "mergechanges/$all",
+ "mergechanges/$all",
+]);
+#diag $stdout;
+unlike($stdout, qr/BEGIN PGP/);
+unlike($stdout, qr/END PGP/);
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+open($fh, '<', \$stdout);
+$merged->parse($fh, 'stdout of mergechanges');
+close($fh);
+is($merged->{Format}, $controls{$source}->{Format});
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+is($merged->{Binary}, 'xdg-desktop-portal-dev');
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(all)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Description}),
+))]);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Files}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{'Checksums-Sha1'}),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{'Checksums-Sha256'}),
+))]);
+
+diag('Format 1.7 and 1.8 are compatible');
+$stdout = capture([
+ $mergechanges,
+ '--indep',
+ "mergechanges/$all",
+ "mergechanges/format-1.7.changes",
+]);
+diag $stdout;
+unlike($stdout, qr/BEGIN PGP/);
+unlike($stdout, qr/END PGP/);
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+open($fh, '<', \$stdout);
+$merged->parse($fh, 'stdout of mergechanges');
+close($fh);
+# Formats 1.8 and 1.7 merge to 1.7
+is($merged->{Format}, '1.7');
+is($merged->{Date}, $controls{$source}->{Date});
+is($merged->{Source}, $controls{$source}->{Source});
+is($merged->{Binary}, 'xdg-desktop-portal-dev');
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(all)]);
+is($merged->{Version}, $controls{$source}->{Version});
+is($merged->{Distribution}, $controls{$source}->{Distribution});
+is($merged->{Urgency}, $controls{$source}->{Urgency});
+is($merged->{Maintainer}, $controls{$source}->{Maintainer});
+is($merged->{'Changed-By'}, $controls{$source}->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Description}),
+))]);
+is($merged->{Changes}, $controls{$source}->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ (split /\n/, $controls{$all}->{Files}),
+))]);
+# Format 1.7 didn't have Checksums-*
+is($merged->{'Checksums-Sha1'}, undef);
+is($merged->{'Checksums-Sha256'}, undef);
+
+diag('Only one');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$source",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{Not enough parameters});
+
+diag('ENOENT');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$source",
+ "mergechanges/does-not-exist.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{ERROR: Cannot read mergechanges/does-not-exist\.changes});
+
+diag('Different description');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$all",
+ "mergechanges/different-description.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{Error: Descriptions do not match});
+
+diag('Different format');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$all",
+ "mergechanges/unsupported-format.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{Error: Changes files have different Format fields});
+
+diag('Different source package');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$all",
+ "mergechanges/different-source.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{Error: Source packages do not match});
+
+diag('Different version');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$all",
+ "mergechanges/different-version.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{ERROR: Version numbers do not match});
+
+diag('Unsupported checksums');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/$all",
+ "mergechanges/unsupported-checksum.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{Error: Unsupported checksum fields});
+
+diag('Unsupported format');
+ok(! verbose_run([
+ $mergechanges,
+ "mergechanges/unsupported-format.changes",
+ "mergechanges/unsupported-format.changes",
+], '>', \$stdout, '2>', \$stderr));
+is($stdout, '');
+like($stderr, qr{Error: Changes files use unknown Format});
+
+diag('Multi-line Binary');
+$stdout = capture([
+ $mergechanges,
+ '--indep',
+ 'mergechanges/linux_4.9.161-1_amd64.changes',
+ 'mergechanges/linux_4.9.161-1_amd64.changes',
+]);
+unlike($stdout, qr/BEGIN PGP/);
+unlike($stdout, qr/END PGP/);
+$merged = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+open($fh, '<', \$stdout);
+$merged->parse($fh, 'stdout of mergechanges');
+close($fh);
+$orig = Dpkg::Control->new(type => CTRL_FILE_CHANGES);
+$orig->load('mergechanges/linux_4.9.161-1_amd64.changes');
+is($merged->{Format}, $orig->{Format});
+is($merged->{Date}, $orig->{Date});
+is($merged->{Source}, $orig->{Source});
+@words = sort split / /, $merged->{Binary};
+is_deeply(\@words, [sort qw(
+ linux-doc-4.9
+ linux-headers-4.9.0-9-common
+ linux-headers-4.9.0-9-common-rt
+ linux-manual-4.9
+ linux-source-4.9
+ linux-support-4.9.0-9
+)]);
+@words = sort split / /, $merged->{Architecture};
+is_deeply(\@words, [sort qw(all source)]);
+is($merged->{Version}, $orig->{Version});
+is($merged->{Distribution}, $orig->{Distribution});
+is($merged->{Urgency}, $orig->{Urgency});
+is($merged->{Maintainer}, $orig->{Maintainer});
+is($merged->{'Changed-By'}, $orig->{'Changed-By'});
+isnt($merged->{Description}, undef);
+@lines = sort split /\n/, $merged->{Description};
+is_deeply(\@lines, [sort(uniq(
+ grep({m/^$/ || m/^(linux-doc-4.9|linux-headers-4.9.0-9-common|linux-headers-4.9.0-9-common-rt|linux-manual-4.9|linux-source-4.9|linux-support-4.9.0-9) - /} (split /\n/, $orig->{Description})),
+))]);
+is($merged->{Changes}, $orig->{Changes});
+@lines = sort split /\n/, $merged->{Files};
+is_deeply(\@lines, [sort(uniq(
+ grep({! /_amd64\./} (split /\n/, $orig->{Files})),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha1'};
+is_deeply(\@lines, [sort(uniq(
+ grep({! /_amd64\./} (split /\n/, $orig->{'Checksums-Sha1'})),
+))]);
+@lines = sort split /\n/, $merged->{'Checksums-Sha256'};
+is_deeply(\@lines, [sort(uniq(
+ grep({! /_amd64\./} (split /\n/, $orig->{'Checksums-Sha256'})),
+))]);
+
+done_testing;
+
+# vim:set sts=4 sw=4 et: