1
0
Fork 0
devscripts/test/test_mergechanges
Daniel Baumann b543f2e88d
Adding upstream version 2.25.15.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-21 11:04:07 +02:00

563 lines
19 KiB
Perl
Executable file

#!/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 Dpkg::IPC;
use File::Temp qw(tempdir);
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 run {
my ($argv, %opts) = @_;
diag("Running: @{$argv}") if $opts{verbose};
delete $opts{verbose};
spawn(
%opts,
exec => $argv,
wait_child => 1,
nocheck => 1,
);
return $? == 0;
}
sub verbose_run {
my ($argv, %opts) = @_;
return run($argv, verbose => 1, %opts);
}
sub capture {
my $output;
my $argv = shift;
ok(verbose_run($argv, to_string => \$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",
], to_string => \$stdout, error_to_string => \$stderr));
is($stdout, '');
like($stderr, qr{Not enough parameters});
diag('ENOENT');
ok(! verbose_run([
$mergechanges,
"mergechanges/$source",
"mergechanges/does-not-exist.changes",
], to_string => \$stdout, error_to_string => \$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",
], to_string => \$stdout, error_to_string => \$stderr));
is($stdout, '');
like($stderr, qr{Error: Descriptions do not match});
diag('Different format');
ok(! verbose_run([
$mergechanges,
"mergechanges/$all",
"mergechanges/unsupported-format.changes",
], to_string => \$stdout, error_to_string => \$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",
], to_string => \$stdout, error_to_string => \$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",
], to_string => \$stdout, error_to_string => \$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",
], to_string => \$stdout, error_to_string => \$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",
], to_string => \$stdout, error_to_string => \$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: