diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:01:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:01:11 +0000 |
commit | 3be121a05dcd170854a8dac6437b29f297a6ff4e (patch) | |
tree | 05cf57183f5a23394eca11b00f97a74a5dfdf79d /test/t | |
parent | Initial commit. (diff) | |
download | devscripts-3be121a05dcd170854a8dac6437b29f297a6ff4e.tar.xz devscripts-3be121a05dcd170854a8dac6437b29f297a6ff4e.zip |
Adding upstream version 2.23.4+deb12u1.upstream/2.23.4+deb12u1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
34 files changed, 6995 insertions, 0 deletions
diff --git a/test/t/common.t b/test/t/common.t new file mode 100755 index 0000000..82e9b53 --- /dev/null +++ b/test/t/common.t @@ -0,0 +1,106 @@ +#!/usr/bin/perl + +package Config::Test; + +use Moo; + +extends 'Devscripts::Config'; + +use constant keys => [ + ['test!', 'TEST', 'bool', 1], + ['str=s', 'STR', qr/^a/, 'ab'], + ['str2=s', 'STR2', qr/^a/, 'bb'], + ['array=s', 'ARRAY', undef, sub { [] }], +]; + +package main; + +use Test::More tests => 39; + +BEGIN { + use_ok('Devscripts::Config'); +} + +my $conf; +$Devscripts::Output::die_on_error = 0; + +@Devscripts::Config::config_files = (); + +ok($conf = Config::Test->new->parse, 'No conf files, no args'); +ok($conf->{test} == 1, ' test=1'); +ok($conf->{str} eq 'ab', ' str=ab'); +ok($conf->{str2} eq 'bb', ' str2=bb'); + +@Devscripts::Config::config_files = ('t/config1'); + +ok($conf = Config::Test->new->parse, 'Conf files, no args'); +ok($conf->{test} == 0, ' test=0'); +ok($conf->{str} eq 'az', ' str=az'); +ok($conf->{str2} eq 'a1', ' str2=a1'); +if (ok(ref $conf->{array}, ' array')) { + ok($conf->{array}->[0] eq "b c", ' "b c" found'); + ok($conf->{array}->[1] eq "a", ' "a" found'); + ok($conf->{array}->[2] eq "d", ' "d" found'); + ok(scalar @{ $conf->{array} } == 3, ' 3 elements'); +} + +@ARGV = ('--noconf'); + +ok($conf = Config::Test->new->parse, '--noconf'); +ok($conf->{test} == 1, ' test=1'); +ok($conf->{str} eq 'ab', ' str=ab'); +ok($conf->{str2} eq 'bb', ' str2=bb'); + +@ARGV = ('--conffile', 't/config2'); + +ok($conf = Config::Test->new->parse, '--conffile t/config2'); +ok($conf->{test} == 1, ' test=1'); +ok($conf->{str} eq 'ab', ' str=ab'); +ok($conf->{str2} eq 'axzx', ' str2=axzx'); + +@ARGV = ('--conffile', '+t/config2'); + +ok($conf = Config::Test->new->parse, '--conffile +t/config2'); +ok($conf->{test} == 0, ' test=0'); +ok($conf->{str} eq 'az', ' str=az'); +ok($conf->{str2} eq 'axzx', ' str2=axzx'); + +@ARGV = ('--test', '--str2=ac'); + +ok($conf = Config::Test->new->parse, '--test --str2=ac'); +ok($conf->{test} == 1, ' test=1'); +ok($conf->{str} eq 'az', ' str=az'); +ok($conf->{str2} eq 'ac', ' str2=ac'); + +@ARGV = ('--noconf', '--str2', 'ac', '--notest'); + +ok($conf = Config::Test->new->parse, '--noconf --no-test --str2=ac'); +ok($conf->{test} == 0, ' test=0'); +ok($conf->{str} eq 'ab', ' str=ab'); +ok($conf->{str2} eq 'ac', ' str2=ac'); + +@ARGV = ('--noconf', '--array', 'a', '--array=b'); +ok($conf = Config::Test->new->parse, '--noconf --array a --array=b'); +ok(ref $conf->{array}, 'Multiple options are allowed'); +ok($conf->{array}->[0] eq 'a', ' first value is a'); +ok($conf->{array}->[1] eq 'b', ' second value is b'); + +# Redirect STDERR to $out; +my $out; +{ + no warnings; + open F, ">&STDERR"; +} +close STDERR; +open STDERR, '>', \$out; +eval { + @ARGV = ('--noconf', '--str2', 'bc'); + $conf = Config::Test->new->parse; +}; + +# Restore STDERR +close STDERR; +open STDERR, ">&F"; +fail($@) if ($@); +ok($out =~ /Bad str2 value/, '--str2=bc is rejected'); + diff --git a/test/t/config1 b/test/t/config1 new file mode 100644 index 0000000..829becc --- /dev/null +++ b/test/t/config1 @@ -0,0 +1,12 @@ +TEST=no +STR=az +STR2=a1 +ARRAY='a "b c" d' +USCAN_SYMLINK=rename +USCAN_VERBOSE=yes +SALSA_TOKEN=xx +SALSA_KGB=yes +SALSA_ENABLE_ISSUES=no +SALSA_EMAIL=ignore +SALSA_ENABLE_MR=yes +SALSA_IRKER=no diff --git a/test/t/config2 b/test/t/config2 new file mode 100644 index 0000000..32d1629 --- /dev/null +++ b/test/t/config2 @@ -0,0 +1 @@ +STR2=axzx diff --git a/test/t/json-cache.t b/test/t/json-cache.t new file mode 100644 index 0000000..a9d8918 --- /dev/null +++ b/test/t/json-cache.t @@ -0,0 +1,25 @@ +use Test::More; + +use strict; + +SKIP: { + eval "use JSON"; + skip "JSON isn't available" if ($@); + use_ok('Devscripts::JSONCache'); + + my %c; + + ok(tie(%c, 'Devscripts::JSONCache', 'test.json'), 'No file'); + $c{a} = 1; + untie %c; + ok(-r 'test.json', 'Cache created'); + ok(tie(%c, 'Devscripts::JSONCache', 'test.json'), 'Reuse file'); + ok($c{a} == 1, 'Value saved'); + untie %c; + unlink 'test.json'; + + my %c2; + eval { tie(%c2, 'Devscripts::JSONCache', 'zzz/test.json') }; + ok($@, "Build refused if write isn't possible"); +} +done_testing(); diff --git a/test/t/salsa-config.t b/test/t/salsa-config.t new file mode 100644 index 0000000..1ee644a --- /dev/null +++ b/test/t/salsa-config.t @@ -0,0 +1,18 @@ +use Test::More tests => 8; + +BEGIN { + use_ok('Devscripts::Salsa::Config'); +} + +@Devscripts::Config::config_files = ('t/config1'); +@ARGV = ('push_repo', '--disable-kgb', '--tagpending', '--irker'); + +ok($conf = Devscripts::Salsa::Config->new->parse, 'Parse'); + +ok(($conf->kgb == 0 and $conf->disable_kgb), 'KGB disabled'); +ok(($conf->tagpending and $conf->disable_tagpending == 0), + 'Tagpending enabled'); +ok(($conf->issues == 'disabled'), 'Enable-issues disabled'); +ok(($conf->email == 0 and $conf->disable_email == 0), 'Email ignored'); +ok(($conf->mr == 'enabled'), 'MR enabled'); +ok(($conf->irker == 1 and $conf->disable_irker == 0), 'Irker enabled'); diff --git a/test/t/salsa.conf b/test/t/salsa.conf new file mode 100644 index 0000000..d14fa84 --- /dev/null +++ b/test/t/salsa.conf @@ -0,0 +1,4 @@ +SALSA_TOKEN=abc +SALSA_API_URL=http://no-exist.xxx/api/v4 +SALSA_KGB_SERVER_URL=http://no-exist.xxx:9418/webhook/?channel= +SALSA_TAGPENDING_SERVER_URL=http://no-exist.xxx:9418/tagpending/ diff --git a/test/t/salsa.pm b/test/t/salsa.pm new file mode 100644 index 0000000..800d1e5 --- /dev/null +++ b/test/t/salsa.pm @@ -0,0 +1,226 @@ +{ + + package MockRESTClient; + use URI; + use Moo; + extends 'GitLab::API::v4::RESTClient'; + + has _mocks => ( + is => 'ro', + default => sub { [] }, + init_arg => undef, + ); + + sub mock_endpoints { + my $self = shift; + + while (@_) { + my $method = shift; + my $path_re = shift; + my $sub = shift; + + push @{ $self->_mocks() }, [$method, $path_re, $sub]; + } + + return; + } + + sub _http_tiny_request { + my ($self, $req_method, $req) = @_; + + die "req_method may only be 'request' at this time" + if $req_method ne 'request'; + + my ($method, $url, $options) = @$req; + + my $path = URI->new($url)->path(); + $path =~ s{^.*api/v4/}{}; + + foreach my $mock (@{ $self->_mocks() }) { + my ($handler_method, $path_re, $sub) = @$mock; + + next if $method ne $handler_method; + + my @captures = ($path =~ $path_re); + next if !@captures; # No captures still returns a 1. + + my ($status, $content) + = $sub->([$method, $url, $options], @captures); + $content = JSON::to_json($content) if ref $content; + + return { + status => $status, + success => ($status =~ m{^2\d\d$}) ? 1 : 0, + defined($content) ? (content => $content) : (), + }; + } + + die "No mock endpoint matched the $method '$path' endpoint"; + } +} + +sub api { + my ($gitdir) = @_; + my @users = ({ + id => 11, + username => 'me', + name => 'Me', + email => 'me@debian.org', + state => 'active' + }); + my @teams = ({ + id => 2099, + name => 'Debian JavaScript Maintainers', + full_name => 'Debian JavaScript Maintainers', + full_path => 'js-team', + }); + my @projects; + my $next_id = 1; + + my $api = GitLab::API::v4->new( + url => 'https://example.com/api/v4', + rest_client_class => 'MockRESTClient', + ); + + $api->rest_client->mock_endpoints( + GET => qr{^user$} => sub { 200, $users[0] }, + GET => qr{^users$} => sub { 200, \@users }, + POST => qr{^users$} => sub { + my ($req) = @_; + my $user = decode_json($req->[2]->{content}); + $user->{id} = $next_id; + $next_id++; + push @users, $user; + return 204; + }, + GET => qr{^users?/(\d+)$} => sub { + my ($req, $id) = @_; + foreach my $user (@users) { + next if $user->{id} != $id; + return 200, $user; + } + return 404; + }, + GET => qr{^users/(\D+)$} => sub { + my ($req, $id) = @_; + foreach my $user (@users) { + next if $user->{username} != $id; + return 200, $user; + } + return 404; + }, + GET => qr{^groups$} => sub { + 200, \@teams; + }, + GET => qr{^groups/([^/]+)$} => sub { + my ($req, $name) = @_; + foreach my $team (@teams) { + next if $team->{full_path} ne $name; + return 200, $team; + } + return 404; + }, + PUT => qr{^users/(\d+)$} => sub { + my ($req, $id) = @_; + my $data = decode_json($req->[2]->{content}); + foreach my $user (@users) { + next if $user->{id} != $id; + %$user = (%$user, %$data,); + return 204; + } + return 404; + }, + DELETE => qr{^users/(\d+)$} => sub { + my ($req, $id) = @_; + my @new; + foreach my $user (@users) { + next if $user->{id} == $id; + push @new, $user; + } + return 404 if @new == @users; + @users = @new; + return 204; + }, + # Projects + POST => qr{^projects$} => sub { + my $content = JSON::from_json($_[0]->[2]->{content}); + mkdir "$gitdir/me/$content->{path}"; + $ENV{"GIT_CONFIG_NOGLOBAL"} = 1; + print +`cd $gitdir/me/$content->{path};git init;git config receive.denyCurrentBranch ignore;cd -`; + $content->{id} = scalar @projects + 1; + $content->{hooks} = []; + $content->{namespace} = { + kind => 'user', + id => 11, + name => 'me', + }; + $content->{path_with_namespace} = 'me/' . $content->{path}; + $content->{web_url} = 'http://no.org/me/' . $content->{path}; + push @projects, $content; + return 200, $content; + }, + GET => qr{^projects/(\d+)/hooks} => sub { + my ($req, $id) = @_; + my $res = eval { $projects[$id - 1]->{hooks} }; + return ($res ? (200, $res) : (404)); + }, + GET => qr{^projects/(\d+)/services/(\w+)} => sub { + my ($req, $id, $service) = @_; + return 404; + }, + GET => qr{^projects$} => sub { + my ($req) = @_; + return (200, \@projects) unless ($req->[1] =~ /search=([^&]+)/); + my $str = $1; + my @res; + foreach (@projects) { + if ($_->{name} =~ /\Q$str\E/) { + push @res, $_; + } + } + return 200, \@res; + }, + GET => qr{^projects/([a-z]+)(?:%2F(\w+))*$} => sub { + my ($req, @path) = @_; + my $repo = pop @path; + my $path = join '/', @path; + foreach (@projects) { + if ($_->{namespace}->{name} eq $path and $_->{path} eq $repo) { + return 200, $_; + } + } + return 404; + }, + GET => qr{^projects/(\d+)$} => sub { + my ($req, $id) = @_; + return 404 unless ($_ = $projects[$id - 1]); + return 200, $_; + }, + PUT => qr{^projects/(\d+)} => sub { + my ($req, $id) = @_; + return 404 unless ($_ = $projects[$id - 1]); + my $content = JSON::from_json($req->[2]->{content}); + foreach my $k (keys %$content) { + $_->{$k} = $content->{$k}; + } + return 200, {}; + }, + POST => qr{^projects/(\d+)/hooks} => sub { + my ($req, $id) = @_; + return 404 unless ($_ = $projects[$id - 1]); + my $content = JSON::from_json($req->[2]->{content}); + push @{ $_->{hooks} }, $content; + return 200, {}; + }, + POST => qr{^projects/(\d+)/repository/branches} => sub { + return 200, {}; + }, + DELETE => qr{^projects/(\d+)/repository/branches/([\w\-\.]+)$} => sub { + return 200, {}; + }, + ); + return $api; +} + +1; diff --git a/test/t/salsa.t b/test/t/salsa.t new file mode 100644 index 0000000..d80978a --- /dev/null +++ b/test/t/salsa.t @@ -0,0 +1,108 @@ +#!/usr/bin/env perl + +my $skip; +use File::Temp 'tempdir'; +use Test::More; +use strict; + +BEGIN { + eval "use Test::Output;use GitLab::API::v4;"; + $skip = $@ ? 1 : 0; +} + +my $pwd = `pwd`; +chomp $pwd; +my ($api, $gitdir); + +sub mkDebianDir { + my $tmpdir = tempdir(CLEANUP => 1); + chdir $tmpdir; + $ENV{"GIT_CONFIG_NOGLOBAL"} = 1; + $ENV{"HOME"} = ""; + system "git init"; + system "git config user.name 'Joe Developer'"; + system 'git config user.email "jd@debian.org"'; + mkdir 'debian'; + open F, ">debian/changelog"; + print F <<EOF; +foobar (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd\@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +EOF + close F; + open F, ">README.md"; + print F <<EOF; +# Salsa test +EOF + system "git add *"; + system "git commit -a -m 'Salsa test'"; + system "git checkout -q -b dev"; + chdir $pwd; + return $tmpdir; +} + +sub run { + my ($result, $out, @list) = @_; + @ARGV = ('--no-cache', @list); + my ($res, $salsa); + combined_like( + sub { + $salsa = Devscripts::Salsa->new({ api => $api }); + $salsa->config->git_server_url($gitdir . '/'); + $res = $salsa->run; + }, + $out, + "command: " . join(' ', @list)); + ok($res =~ /^$result$/i, " result is $result"); +} + +sub run_debug { + my ($result, $out, @list) = @_; + @ARGV = ('--no-cache', @list); + my ($res, $salsa); + $salsa = Devscripts::Salsa->new({ api => $api }); + $salsa->config->git_server_url($gitdir . '/'); + $res = $salsa->run; +} + +SKIP: { + skip "Missing dependencies" if ($skip); + require './t/salsa.pm'; + $gitdir = tempdir(CLEANUP => 1); + sleep 1; + mkdir "$gitdir/me" or die "$gitdir/me: $!"; + + $api = api($gitdir); + + use_ok 'Devscripts::Salsa'; + $Devscripts::Output::die_on_error = 0; + @Devscripts::Config::config_files = ('t/salsa.conf'); + + # Search methods + run(0, qr/Id\s*:\s*11\nUsername\s*:\s*me/s, 'whoami'); + run(0, qr/Id\s*:\s*2099\nName/s, 'search_group', 'js-team'); + run(0, qr/Id\s*:\s*2099\nName/s, 'search_group', 2099); + run(0, qr/Id.*\nUsername\s*: me/s, 'search_user', 'me'); + run(0, qr/Id.*\nUsername\s*: me/s, 'search_user', 'm'); + run(0, qr/Id.*\nUsername\s*: me/s, 'search_user', 11); + + # Project methods + my $repo = mkDebianDir; + run(0, qr/Project .*created/s, '-C', $repo, '--verbose', 'push_repo', '.'); + chdir $pwd; + $repo = tempdir(CLEANUP => 1); + run(0, qr/KGB hook added.*Tagpending hook added/s, + 'update_repo', '--kgb', '--irc=debian', '--tagpending', 'foobar'); + run(0, qr/foobar\s*:\s*OK/s, + 'update_safe', '--kgb', '--irc=debian', '--tagpending', 'foobar'); + run(0, qr{Full path\s*:\s*me/foobar}, 'search', 'foobar'); + run(0, qr{Configuring foobar}, + 'rename_branch', 'foobar', '--source-branch=dev', + '--dest-branch=dev2'); +} + +done_testing; + +1; diff --git a/test/t/uscan-config.t b/test/t/uscan-config.t new file mode 100644 index 0000000..5209924 --- /dev/null +++ b/test/t/uscan-config.t @@ -0,0 +1,20 @@ +use Test::More tests => 8; + +BEGIN { + use_ok('Devscripts::Uscan::Config'); + use_ok('Devscripts::Uscan::Output'); +} + +@Devscripts::Config::config_files = ('t/config1'); +@ARGV = ( '--download-version', '1.0', '-dd', '--no-verbose' ); + +ok( + $conf = Devscripts::Uscan::Config->new->parse, + 'USCAN_SYMLINK=rename + --download-version' +); + +ok($conf->symlink eq 'rename', ' symlink=rename'); +ok($conf->download_version eq '1.0',' download_version=1.0'); +ok($conf->user_agent =~ /^Debian uscan/, qq' user agent starts with "Debian uscan" ($conf->{user_agent})'); +ok($conf->download == 2, 'Force download'); +ok($verbose == 0, 'Verbose is disabled'); diff --git a/test/test_annotate-output b/test/test_annotate-output new file mode 100755 index 0000000..ca367be --- /dev/null +++ b/test/test_annotate-output @@ -0,0 +1,47 @@ +#!/bin/sh + +# Copyright (C) 2012, James McCoy <jamessan@debian.org> +# +# 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/>. + +set -u + +if test "${1:-}" = --installed; then + COMMAND=annotate-output + shift +else + COMMAND="../scripts/annotate-output.sh" +fi + +WORKDIR="$(readlink -f "${0%/*}")" + +testSwallowedNewline() { + expected="% O: foo% I: Finished with exitcode 0" + actual="$($COMMAND +%% echo -n foo | grep O:)" + assertEquals 'incomplete line found' "${expected}" "${actual}" +} + +testBackslashes() { + expected='% O: \f\o\o' + actual="$($COMMAND +%% printf '%s\n' '\f\o\o' | grep O:)" + assertEquals 'backslashes echoed' "${expected}" "${actual}" +} + +testLeadingWhitespace() { + expected='% O: foo' + actual="$($COMMAND +%% printf '%s\n' ' foo' | grep O:)" + assertEquals 'leading whitespace preserved' "${expected}" "${actual}" +} + +. shunit2 diff --git a/test/test_checkbashisms b/test/test_checkbashisms new file mode 100755 index 0000000..38d4c4a --- /dev/null +++ b/test/test_checkbashisms @@ -0,0 +1,221 @@ +#!/bin/sh + +# Copyright (C) 2012, Benjamin Drung <bdrung@debian.org> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -u + +if test "${1:-}" = --installed; then + COMMAND=checkbashisms + shift +else + # shellcheck disable=SC2034 + COMMAND="../scripts/checkbashisms.pl" +fi + +WORKDIR="$(readlink -f "${0%/*}")" + +. "${0%/*}/shunit2-helper-functions.sh" + +clean() { + cd "$WORKDIR" + runCommand "$1" "" "" 0 +} + +found() { + cd "$WORKDIR" + runCommand "$1" "" "$2" 1 +} + +test_531327() { + clean "bashisms/531327.sh" +} + +test_535368() { + clean "-f bashisms/535368.mk" +} + +test_808271() { + found "bashisms/808271.sh" "$(cat bashisms/808271.sh.out)" +} + +test_arith() { + found "bashisms/arith.sh" "$(cat bashisms/arith.sh.out)" +} + +test_array_expansion() { + found "bashisms/array-expansion.sh" "$(cat bashisms/array-expansion.sh.out)" +} + +test_ash_setvar() { + found "bashisms/ash-setvar.sh" "$(cat bashisms/ash-setvar.sh.out)" +} + +test_basic() { + found "-f bashisms/basic.mk" "$(cat bashisms/basic.mk.out)" +} + +test_basic_bash() { + clean "-f bashisms/basic-bash.mk" +} + +test_brace_expansion() { + found "-f bashisms/brace-expansion.sh" "$(cat bashisms/brace-expansion.sh.out)" +} + +test_basic_bash_override() { + clean "-f bashisms/basic-bash-override.mk" +} + +test_case_modification() { + found "-f bashisms/case-modification.sh" "$(cat bashisms/case-modification.sh.out)" +} + +test_comments_in_quoted_strings1() { + clean "bashisms/comments-in-quoted-strings1.sh" +} + +test_comments_in_quoted_strings2() { + clean "bashisms/comments-in-quoted-strings2.sh" +} + +test_command() { + found "bashisms/command.sh" "$(cat bashisms/command.sh.out)" +} + +test_comments_parsing_fns() { + found "bashisms/comments-parsing-fns.sh" "$(cat bashisms/comments-parsing-fns.sh.out)" +} + +test_coproc() { + found "bashisms/coproc.sh" "$(cat bashisms/coproc.sh.out)" +} + +test_dynamic_length() { + found "bashisms/dynamic-length.sh" "$(cat bashisms/dynamic-length.sh.out)" +} + +test_exit_code() { + found "bashisms/exit-code.sh" "$(cat bashisms/exit-code.sh.out)" +} + +test_fail2ban() { + clean "bashisms/fail2ban.sh" +} + +test_fps() { + found "bashisms/fps.sh" "$(cat bashisms/fps.sh.out)" +} + +test_functions() { + found "bashisms/functions.sh" "$(cat bashisms/functions.sh.out)" +} + +test_gettext() { + found "bashisms/gettext.sh" "$(cat bashisms/gettext.sh.out)" +} + +test_glob_ignore() { + found "bashisms/glob-ignore.sh" "$(cat bashisms/glob-ignore.sh.out)" +} + +test_hash() { + found "bashisms/hash.sh" "$(cat bashisms/hash.sh.out)" +} + +test_heredocs() { + found "bashisms/heredocs.sh" "$(cat bashisms/heredocs.sh.out)" +} + +test_heredoc_with_dash() { + clean "bashisms/heredoc-with-dash.sh" +} + +test_heredoc_with_others() { + clean "bashisms/heredoc-with-others.sh" +} + +test_jobs() { + found "bashisms/jobs.sh" "$(cat bashisms/jobs.sh.out)" +} + +test_line_continuation() { + found "bashisms/line-continuation.sh" "$(cat bashisms/line-continuation.sh.out)" +} + +test_negations() { + found "bashisms/negations.sh" "$(cat bashisms/negations.sh.out)" +} + +test_other_vars() { + found "bashisms/other-vars.sh" "$(cat bashisms/other-vars.sh.out)" +} + +test_printf() { + found "bashisms/printf.sh" "$(cat bashisms/printf.sh.out)" +} + +test_quoted_strings() { + found "bashisms/quoted-strings.sh" "$(cat bashisms/quoted-strings.sh.out)" +} + +test_return() { + found "bashisms/return.sh" "$(cat bashisms/return.sh.out)" +} + +test_shell_vars() { + clean "-f bashisms/shell-vars.mk" +} + +test_source() { + found "bashisms/source" "$(cat bashisms/source.out)" +} + +test_special_case() { + found "bashisms/special-case.sh" "$(cat bashisms/special-case.sh.out)" +} + +test_special_expansions() { + found "bashisms/special-expansions.sh" "$(cat bashisms/special-expansions.sh.out)" +} + +test_subshell_no_arith() { + clean "bashisms/subshell-no-arith.sh" +} + +test_tilde_expansion() { + found "bashisms/tilde-expansion.sh" "$(cat bashisms/tilde-expansion.sh.out)" +} + +test_traps() { + found "bashisms/traps.sh" "$(cat bashisms/traps.sh.out)" +} + +test_underscore_var() { + found "bashisms/underscore-var.sh" "$(cat bashisms/underscore-var.sh.out)" +} + +test_unknown_fns() { + found "bashisms/unknown-fns.sh" "$(cat bashisms/unknown-fns.sh.out)" +} + +test_unterminated_string() { + clean "bashisms/unterminated-string.sh" +} + +test_unterminated_string2() { + clean "bashisms/unterminated-string2.sh" +} + +. shunit2 diff --git a/test/test_dd-list b/test/test_dd-list new file mode 100755 index 0000000..5d741d2 --- /dev/null +++ b/test/test_dd-list @@ -0,0 +1,47 @@ +#!/bin/sh + +# Copyright (C) 2012, James McCoy <jamessan@debian.org> +# +# 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/>. + +set -u + +WORKDIR="$(readlink -f "${0%/*}")" + +if test "${1:-}" = --installed; then + COMMAND=dd-list + shift +else + COMMAND="$WORKDIR/../scripts/dd-list.pl" +fi + +testBinariesFromSameSource() { + $COMMAND -s ${WORKDIR}/dd-list/sources vim-gtk vim-nox 2>&1 >/dev/null + rc=$? + assertEquals 'packages found' 0 $rc +} + +testExtraSourceOnlyIgnored() { + $COMMAND -s ${WORKDIR}/dd-list/sources bzip2 >$SHUNIT_TMPDIR/extra-source.out + + assertFalse 'Jorge listed as uploader' "grep -q Jorge $SHUNIT_TMPDIR/extra-source.out" +} + +testUseOnlyLatestVersion() { + $COMMAND -s ${WORKDIR}/dd-list/sources subversion >$SHUNIT_TMPDIR/latest-version.out + + assertFalse 'Troy Heber listed as uploader' "grep -q Troy $SHUNIT_TMPDIR/latest-version.out" +} + +. shunit2 diff --git a/test/test_debchange b/test/test_debchange new file mode 100755 index 0000000..f4bca26 --- /dev/null +++ b/test/test_debchange @@ -0,0 +1,251 @@ +#!/bin/bash + +# Copyright (C) 2012, Benjamin Drung <bdrung@debian.org> +# © 2017 Mattia Rizzolo <mattia@debian.org> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -u + +if test "${1:-}" = --installed; then + COMMAND="dch --no-conf" + shift +else + COMMAND="perl -I ${0%/*}/../lib ${0%/*}/../scripts/debchange.pl --no-conf" +fi + +. "${0%/*}/shunit2-helper-functions.sh" + +setUp() { + CHANGELOG="${SHUNIT_TMPDIR}/changelog" + DEBFULLNAME="Raphaël Hertzog" + DEBEMAIL="hertzog@debian.org" + export DEBFULLNAME DEBEMAIL +} + +tearDown() { + unset CHANGELOG DEBFULLNAME DEBEMAIL +} + +runCommand2() { + local param="$1" + local exp_stdout="$2" + local exp_stderr="$3" + local exp_retval=$4 + local stdoutF="${SHUNIT_TMPDIR}/stdout" + local stderrF="${SHUNIT_TMPDIR}/stderr" + eval "${COMMAND} $param" > ${stdoutF} 2> ${stderrF} + # Strip distribution data outdated warnings (caused by outdate distro-info-data). + cat $stderrF | \ + grep -v "^Distribution data outdated. Please check for an update for distro-info-data. See /usr/share/doc/distro-info-data/README.Debian for details." | \ + grep -v '^debchange[^ ]* warning: Unable to determine the current Ubuntu development release. Using UNRELEASED instead.$' > ${stderrF}.tmp + mv ${stderrF}.tmp ${stderrF} + retval=$? + assertEquals "standard output of ${COMMAND} $param\n" "$exp_stdout" "$(cat ${stdoutF})" + assertEquals "error output of ${COMMAND} $param\n" "$exp_stderr" "$(cat ${stderrF})" + assertEquals "return value of ${COMMAND} $param\n" $exp_retval $retval +} + +success() { + runCommand2 "-c \"$CHANGELOG\" $1" "" "" 0 +} + +checkUbuntuDevelAvailable() { + if ubuntu-distro-info --devel 2>/dev/null >&2; then + # distro-info-data knows of the current devel release + true + else + # distro-info-data doesn't know of the current devel release + false + fi +} + +checkVersion() { + local start_param="$1" + local param="$2" + local start_version="$3" + local expected_version="$4" + rm -f "$CHANGELOG" + success "--create $start_param --package test-package -v $start_version \"Devscripts Test Suite.\"" + success "$param \"Version test.\"" + local version=$(dpkg-parsechangelog -l"$CHANGELOG" -SVersion) + assertEquals "\"dch $param\" from version $start_version" "$expected_version" "$version" +} + +checkDebianDistribution() { + checkVersion "--vendor Debian -D unstable" "--vendor Debian -i -D $1" "1.0-1" "1.0-2" +} + +checkDebianVersion() { + checkVersion "--vendor Debian -D unstable" "--vendor Debian $1" "$2" "$3" +} + +checkUbuntuVersion() { + checkVersion "--vendor Debian -D unstable" "--vendor Ubuntu $1" "$2" "$3" +} + +testDebianDistributions() { + checkDebianDistribution "trixie" + checkDebianDistribution "trixie-security" + checkDebianDistribution "bookworm" + checkDebianDistribution "bookworm-proposed-updates" + checkDebianDistribution "bookworm-security" + checkDebianDistribution "bullseye" + checkDebianDistribution "bullseye-security" + checkDebianDistribution "buster" + checkDebianDistribution "buster-security" + checkDebianDistribution "experimental" + checkDebianDistribution "oldstable" + checkDebianDistribution "oldstable-proposed-updates" + checkDebianDistribution "oldoldstable" + checkDebianDistribution "oldoldstable-proposed-updates" + checkDebianDistribution "proposed-updates" + checkDebianDistribution "stable" + checkDebianDistribution "stable-proposed-updates" + checkDebianDistribution "testing" + checkDebianDistribution "testing-proposed-updates" + checkDebianDistribution "UNRELEASED" +} + +testDebianIncrement() { + checkDebianVersion "-i" "1.0-1" "1.0-2" + checkDebianVersion "-i" "12" "13" +} + +testUbuntuIncrement() { + if ! checkUbuntuDevelAvailable; then + echo "No known Ubuntu devel release known, skipping related tests" + startSkipping + fi + checkUbuntuVersion "-i" "12" "12ubuntu1" + checkUbuntuVersion "-i" "3.4" "3.4ubuntu1" + checkUbuntuVersion "-i" "3.4.5" "3.4.5ubuntu1" + checkUbuntuVersion "-i" "5.6-7" "5.6-7ubuntu1" + checkUbuntuVersion "-i" "5.6-7.1" "5.6-7.1ubuntu1" + checkUbuntuVersion "-i" "5.6-7.1.8" "5.6-7.1.8ubuntu1" + checkUbuntuVersion "-i" "2.13-14build5" "2.13-14ubuntu1" + checkUbuntuVersion "-i" "0.45-2ubuntu3" "0.45-2ubuntu4" + checkUbuntuVersion "-i" "0.45-2ubuntu3.1" "0.45-2ubuntu3.2" + checkUbuntuVersion "-i" "0.45-2ubuntu3.1.0" "0.45-2ubuntu3.1.1" +} + +testUbuntuRebuild() { + if ! checkUbuntuDevelAvailable; then + echo "No known Ubuntu devel release known, skipping related tests" + startSkipping + fi + checkUbuntuVersion "-R" "3.4" "3.4build1" + checkUbuntuVersion "-R" "2.0-4" "2.0-4build1" + checkUbuntuVersion "-R" "1.42-4ubuntu5" "1.42-4ubuntu6" + checkUbuntuVersion "-R" "0.1-2build3" "0.1-2build4" +} + +verifyMaintainer() { + local maintainer="$(dpkg-parsechangelog -l"$CHANGELOG" -SMaintainer)" + assertEquals "\"$1\"" "$DEBFULLNAME <$DEBEMAIL>" "$maintainer" +} + +testEncoding() { + rm -f "$CHANGELOG" + success "--create -D unstable --package test-package -v 1.0-1 \"First upload\"" + verifyMaintainer "dch --create" + + success "-a \"Some change\"" + verifyMaintainer "dch -a" + + success "-i \"Second upload\"" + verifyMaintainer "dch -i" + + success "-e \"Another change\"" + verifyMaintainer "dch -e" + + success "-n NMU" + verifyMaintainer "dch -n" + + success "-v 1.1-1 \"New upstream\"" + verifyMaintainer "dch -v" + + success "--bin-nmu \"Rebuild against libfoo\"" + verifyMaintainer "dch --bin-nmu" + + success "-q \"QA upload\"" + verifyMaintainer "dch -q" + + success "-s \"Security upload\"" + verifyMaintainer "dch -s" + + success "-s \"LTS Security upload\"" + verifyMaintainer "dch --lts" + + success "--bpo \"Backports upload\"" + verifyMaintainer "dch --bpo" + + success "--stable \"Stable upload\"" + verifyMaintainer "dch --stable" +} + +verifyEntryLines() { + success "--vendor Debian $1" + local changes="$(dpkg-parsechangelog -l"$CHANGELOG" -SChanges | grep -F '*')" + assertEquals "\"$changes\"" 1 "$(echo "$changes" | wc -l)" +} + +# Any options which automatically add their own entry to the changelog should +# elide an empty entry if the user passes an empty string as the entry. +testEmptyMessage() { + rm -f "$CHANGELOG" + success "--create -D unstable --package test-package -v 1.0-1 'First upload'" + + verifyEntryLines "--nmu ''" + + verifyEntryLines "--bin-nmu ''" + + verifyEntryLines "--qa ''" + + verifyEntryLines "--security ''" + + verifyEntryLines "--bpo ''" + + verifyEntryLines "--team ''" +} + +verifyGuessedDistribution() { + # $1 → initial suite + # $2 → action + # $3 → expected suite after the action + rm -f "$CHANGELOG" + vdeb="--vendor Debian" + success "$vdeb --create -D $1 --package test-package -v 1.0-1 'First upload'" + success "$vdeb $2 'Second Upload'" + success "$vdeb -r ''" + local dist="$(dpkg-parsechangelog -l"$CHANGELOG" -SDistribution)" + assertEquals "$3" "$dist" +} + +testGuessedDistribution() { + verifyGuessedDistribution unstable -i unstable + verifyGuessedDistribution experimental -i experimental + verifyGuessedDistribution bookworm-backports -i bookworm-backports + verifyGuessedDistribution trixie -i trixie + verifyGuessedDistribution unstable --bpo bookworm-backports + verifyGuessedDistribution unstable --stable bookworm +} + +testSpecialCharacterMaintainer() { + rm -f "$CHANGELOG" + export DEBFULLNAME='\k' + success "--create -D unstable --package test-package -v 1.0-1 \"First upload\"" + success "-a \"Some change\"" +} + +. shunit2 diff --git a/test/test_debdiff b/test/test_debdiff new file mode 100755 index 0000000..8043574 --- /dev/null +++ b/test/test_debdiff @@ -0,0 +1,35 @@ +#!/bin/sh + +# Copyright (C) 2013, James McCoy <jamessan@debian.org> +# +# 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/>. + +set -u + +if test "${1:-}" = --installed; then + COMMAND="debdiff --no-conf" + shift +else + COMMAND="perl -I ${0%/*}/../lib ${0%/*}/../scripts/debdiff.pl --no-conf" +fi + +WORKDIR="$(readlink -f "${0%/*}")" + +test() { + $COMMAND ${WORKDIR}/debdiff/devscripts_2.13.0_any.deb ${WORKDIR}/debdiff/devscripts_2.13.1_any.deb >/dev/null 2>/dev/null + rc=$? + assertEquals 'difference found, no errors' 1 $rc +} + +. shunit2 diff --git a/test/test_debi b/test/test_debi new file mode 100755 index 0000000..f3206f5 --- /dev/null +++ b/test/test_debi @@ -0,0 +1,285 @@ +#!/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/>. + +=head1 NAME + +test_debi - unit test for debi + +=head1 WARNING + +This test requires root privileges, and installs and removes packages. +Please run it in an expendable environment, such as via +one of the B<autopkgtest-virt-*> autopkgtest backends. + +=head1 DESCRIPTION + +This test verifies that debi's B<--with-depends> and B<--upgrade> interact +as expected. + +=cut + +use autodie; +use strict; +use warnings; + +use Cwd qw(getcwd); +use Digest::MD5; +use Digest::SHA; +use File::Temp qw(tempdir); +use IPC::Run qw(run); +use Test::More; + +use Dpkg::Control; + +my $srcdir = getcwd; +my $top_srcdir = getcwd . '/..'; +my @debi = ("$top_srcdir/scripts/debi.pl", '--no-conf'); +my $tmp; + +if (defined $ARGV[0] && $ARGV[0] eq '--installed') { + $debi[0] = 'debi'; +} +else { + $ENV{PATH} = "$top_srcdir/scripts:$ENV{PATH}"; +} + +sub verbose_run { + my $argv = shift; + diag("Running: @{$argv}"); + my $ret = run($argv, @_); + if ($ret) { + diag("=> success"); + } else { + diag("=> exit status $?"); + } + return $ret; +} + +sub capture { + my $output; + my $argv = shift; + ok(verbose_run($argv, '>', \$output), "@{$argv}"); + chomp $output; + return $output; +} + +sub make_deb { + my ($name, $version, $depends) = @_; + mkdir "$tmp/deb" unless -d "$tmp/deb"; + mkdir "$tmp/deb/DEBIAN" unless -d "$tmp/deb/DEBIAN"; + open my $fh, '>', "$tmp/deb/DEBIAN/control"; + print {$fh} "Package: devscripts-test-$name\n"; + print {$fh} "Section: misc\n"; + print {$fh} "Priority: optional\n"; + print {$fh} "Maintainer: nobody\n"; + print {$fh} "Version: $version\n"; + print {$fh} "Architecture: all\n"; + print {$fh} "Depends: $depends\n"; + print {$fh} "Description: a package\n"; + close $fh; + + my $deb = "$tmp/devscripts-test-${name}_${version}_all.deb"; + if (!run(['dpkg-deb', '-b', "$tmp/deb", $deb])) { + BAIL_OUT("Failed to build $name package from $tmp/deb"); + } +} + +sub make_changes { + my @packages = @_; + my $changes = "$tmp/foo.changes"; + my $ctrl = Dpkg::Control->new(type => CTRL_FILE_CHANGES); + $ctrl->{Format} = '1.8'; + $ctrl->{Source} = 'devscripts-test'; + $ctrl->{Files} = "\n"; + $ctrl->{'Checksums-Sha256'} = "\n"; + + foreach my $name (@packages) { + my $md5 = Digest::MD5->new; + my $sha256 = Digest::SHA->new(256); + open my $fh, '<', "$tmp/devscripts-test-${name}_1_all.deb"; + binmode $fh; + $md5->addfile($fh); + seek $fh, 0, 0; + $sha256->addfile(*$fh); + close $fh; + my $hash = $md5->hexdigest; + my @stat = stat "$tmp/devscripts-test-${name}_1_all.deb"; + my $size = $stat[7]; + + $ctrl->{Files} + .= "$hash $size misc optional devscripts-test-${name}_1_all.deb\n"; + $hash = $sha256->hexdigest; + $ctrl->{'Checksums-Sha256'} + .= "$hash $size devscripts-test-${name}_1_all.deb\n"; + } + diag $ctrl; + $ctrl->save($changes); +} + +sub purge_packages { + ok( + verbose_run([ + 'dpkg', + '--purge', + 'devscripts-test-already-installed', + 'devscripts-test-dependency', + 'devscripts-test-gains-dependency', + 'devscripts-test-gains-local-dependency', + 'devscripts-test-not-installed', + 'hello', + ])); +} + +sub version_of { + my $output; + my $ignored; + run(['dpkg-query', '-W', '-f', '${Version}', shift], + '>', \$output, '2>', \$ignored); + chomp $output; + return $output; +} + +sub status_of { + my $output; + my $ignored; + run(['dpkg-query', '-W', '-f', '${Status}', shift], + '>', \$output, '2>', \$ignored); + chomp $output; + return $output; +} + +plan skip_all => 'not root' unless $< == 0 && $> == 0; + +$tmp = tempdir(CLEANUP => 1); +open my $fh, '>', "$tmp/yes.conf"; +print {$fh} qq{Apt::Get::Assume-Yes "true";\n}; +print {$fh} qq{Apt::Get::allow-downgrades "true";\n}; +close $fh; +$ENV{APT_CONFIG} = "$tmp/yes.conf"; + +make_deb('already-installed', '0', 'base-files'); +make_deb('already-installed', '1', 'base-files'); +make_deb('already-installed', '2', 'base-files'); +make_deb('not-installed', '1', 'base-files'); +make_deb('gains-local-dependency', '0', 'base-files'); +make_deb('gains-local-dependency', '1', 'devscripts-test-dependency'); +make_deb('dependency', '1', 'base-files'); +make_deb('gains-dependency', '0', 'base-files'); +make_deb('gains-dependency', '1', 'hello'); + +diag('debi foo.changes will upgrade existing packages and install new ones'); +purge_packages(); +ok( + verbose_run( + ['dpkg', '-i', "$tmp/devscripts-test-already-installed_0_all.deb",])); +make_changes(qw(already-installed not-installed)); +ok(verbose_run([@debi, "$tmp/foo.changes",]), 'plain debi succeeds'); +is(version_of('devscripts-test-already-installed'), + '1', 'already installed package was upgraded'); +is(version_of('devscripts-test-not-installed'), + '1', 'not-installed package was installed (regressed in #932640)'); + +diag('debi foo.changes will also downgrade existing packages'); +purge_packages(); +ok( + verbose_run( + ['dpkg', '-i', "$tmp/devscripts-test-already-installed_2_all.deb",])); +make_changes(qw(already-installed)); +ok(verbose_run([@debi, "$tmp/foo.changes",]), 'plain debi succeeds'); +is(version_of('devscripts-test-already-installed'), + '1', 'already installed package was downgraded'); + +diag('debi --upgrade will upgrade/downgrade existing packages, only'); +purge_packages(); +ok( + verbose_run( + ['dpkg', '-i', "$tmp/devscripts-test-already-installed_2_all.deb",])); +make_changes(qw(already-installed not-installed)); +ok(verbose_run([@debi, '--upgrade', "$tmp/foo.changes",]), + 'debi --upgrade succeeds'); +is(version_of('devscripts-test-already-installed'), + '1', 'already installed package was downgraded'); +is(version_of('devscripts-test-not-installed'), + '', 'not-installed package was not installed'); + +diag('it is OK if debi --upgrade does nothing'); +purge_packages(); +make_changes(qw(not-installed)); +ok(verbose_run([@debi, '--upgrade', "$tmp/foo.changes",]), + 'debi --upgrade succeeds'); +is(version_of('devscripts-test-not-installed'), + '', 'not-installed package was not installed'); + +diag('debi without --with-depends does not try to satisfy dependencies'); +purge_packages(); +ok( + verbose_run( + ['dpkg', '-i', "$tmp/devscripts-test-gains-dependency_0_all.deb",])); +make_changes(qw(gains-dependency)); +ok(!verbose_run([@debi, "$tmp/foo.changes",]), + 'debi without --with-depends does not install dependency'); +# It's OK for it to either be unpacked but fail to configure, or be +# left at version 0. +isnt( + version_of('devscripts-test-gains-dependency') . "::" + . status_of('devscripts-test-gains-dependency'), + '1::install ok installed', + 'package with a dependency was not installed' +); +is(version_of('hello'), '', 'third party dependency was not installed'); + +diag('debi --with-depends does satisfy dependencies'); +purge_packages(); +make_changes(qw(gains-dependency)); +ok(verbose_run([@debi, '--with-depends', "$tmp/foo.changes",]), + 'debi --with-depends succeeds'); +is(version_of('devscripts-test-gains-dependency'), + '1', 'package with a dependency was installed'); +isnt(version_of('hello'), '', 'third party dependency was installed'); + +diag('debi --upgrade --with-depends does satisfy new dependencies'); +purge_packages(); +ok( + verbose_run( + ['dpkg', '-i', "$tmp/devscripts-test-gains-dependency_0_all.deb",])); +make_changes(qw(gains-dependency not-installed)); +ok(verbose_run([@debi, '--with-depends', '--upgrade', "$tmp/foo.changes",]), + 'debi --with-depends --upgrade succeeds'); +is(version_of('devscripts-test-gains-dependency'), + '1', 'package with a dependency was installed'); +isnt(version_of('hello'), '', 'third party dependency was installed'); +is(version_of('devscripts-test-not-installed'), + '', 'not-installed package was not installed (#932963)'); + +purge_packages(); +verbose_run( + ['dpkg', '-i', "$tmp/devscripts-test-gains-local-dependency_0_all.deb",]); +make_changes(qw(dependency gains-local-dependency)); +ok( + verbose_run([@debi, '--upgrade', '--with-depends', "$tmp/foo.changes",]), + 'corner case from #932963: debi --upgrade --with-depends can cope with ' + . 'a new dependency on a binary from the same source' +); +is(version_of('devscripts-test-gains-local-dependency'), + '1', 'the package we wanted to upgrade is upgraded'); +is(version_of('devscripts-test-dependency'), + '1', + 'the new dependency of the package we wanted to upgrade is installed'); + +purge_packages(); +done_testing; diff --git a/test/test_debrepro b/test/test_debrepro new file mode 100755 index 0000000..077be1e --- /dev/null +++ b/test/test_debrepro @@ -0,0 +1,46 @@ +#!/bin/sh + +# Copyright (C) 2018, Antonio Terceiro <terceiro@debian.org> +# +# 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/>. + +set -u + +DEB_HOST_OS="$(dpkg-architecture -qDEB_HOST_ARCH_OS)" +if [ "$DEB_HOST_OS" = "kfreebsd" ]; then + # kbsd has a non-working semaphore, that is needed here. + echo "This test is not supported on $(dpkg-architecture -qDEB_HOST_ARCH), skipping" + exit 0 +fi + +if test "${1:-}" = --installed; then + debrepro="debrepro --skip filesystem-ordering" + shift +else + debrepro="${0%/*}/../scripts/debrepro.sh --skip filesystem-ordering" +fi + +samples="${0%/*}/debrepro" + +. "${0%/*}/test_helper.sh" + +test_reproducible() { + assertPasses $debrepro $samples/reproducible +} + +test_unreproducible() { + assertFails $debrepro $samples/unreproducible +} + +. shunit2 diff --git a/test/test_debsign b/test/test_debsign new file mode 100755 index 0000000..9c7ccf5 --- /dev/null +++ b/test/test_debsign @@ -0,0 +1,114 @@ +#!/bin/sh + +# Copyright (C) 2018, Chris Lamb <lamby@debian.org> +# +# 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/>. + +set -u + +WORKDIR="$(readlink -f "${0%/*}")" + +if test "${1:-}" = --installed; then + COMMAND="debsign --no-conf" + shift +else + COMMAND="$WORKDIR/../scripts/debsign.sh --no-conf" +fi + +GPG=gpg +GPGHOME=$(mktemp -d -p /tmp gpg.XXXXX) +if ! command -v $GPG >/dev/null 2>&1; then + echo "$GPG missing" + GPG=gpg2 + if ! command -v $GPG >/dev/null 2>&1; then + echo "$GPG missing" + exit 1 + fi +fi + +oneTimeSetUp () { + $GPG -v --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --output $GPGHOME/secring.gpg --dearmor $WORKDIR/debsign/private_key.asc + + $GPG -v --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --output $GPGHOME/pubring.gpg --dearmor $WORKDIR/debsign/public_key.asc + + export GNUPGHOME=$GPGHOME +} + +oneTimeTearDown () { + gpgconf --homedir "$GPGHOME" --verbose --kill gpg-agent + rm -rf "$GPGHOME" +} + +setUp() { + TEMPDIR=$(mktemp -d -p /tmp debsign.XXXXX) + cp $WORKDIR/debsign/* $TEMPDIR + CHANGES=$(echo $TEMPDIR/*changes) +} + +tearDown() { + rm -rf $TEMPDIR +} + +assertSigned() { + expected=$1 + shift + $COMMAND "$@" $CHANGES >$TEMPDIR/stdout 2>$TEMPDIR/stderr + rc=$? + assertEquals 'error code' $expected $rc +} + +testEmailKeyID () { + assertSigned 0 -k none@debian.org +} + +testShortKeyID () { + assertSigned 1 -k 72543FAF + assertTrue 'error not seen' "grep -q 'short key ID' $TEMPDIR/stderr" +} + +testPrefixedShortKeyID () { + assertSigned 1 -k 0x72543FAF + assertTrue 'error not seen' "grep -q 'short key ID' $TEMPDIR/stderr" +} + +testLongKeyID() { + assertSigned 0 -k C77E2D6872543FAF + assertTrue 'not signed' "grep -q 'BEGIN PGP SIGNATURE' $CHANGES" +} + +testPrefixedLongKeyID() { + assertSigned 0 -k 0xC77E2D6872543FAF + assertTrue 'not signed' "grep -q 'BEGIN PGP SIGNATURE' $CHANGES" +} + +testFingerprintKeyID () { + assertSigned 0 -k CF218F0E7EABF584B7E20402C77E2D6872543FAF +} + +testUnknownKeyID () { + assertSigned 2 -k AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + assertTrue 'warning not seen' "grep -q 'No secret key' $TEMPDIR/stderr" +} + +testNameKeyID () { + assertSigned 0 -k 'uscan test key (no secret)' +} + +testFullNameAsKeyID () { + assertSigned 0 -k 'uscan test key (no secret) <none@debian.org>' +} + +. shunit2 diff --git a/test/test_helper.sh b/test/test_helper.sh new file mode 100644 index 0000000..579780c --- /dev/null +++ b/test/test_helper.sh @@ -0,0 +1,26 @@ +setUp() { + tmpdir=$(mktemp -d) + log="$tmpdir/log" +} + +tearDown() { + rm -rf "$tmpdir" +} + +assertPasses() { + local rc=0 + "$@" > "$log" 2>&1 || rc=$? + if [ "$rc" -ne 0 ]; then + cat "$log" + fail "command failed: «$*» (expected pass)" + fi +} + +assertFails() { + local rc=0 + "$@" > "$log" 2>&1 || rc=$? + if [ "$rc" -eq 0 ]; then + cat "$log" + fail "command passed: «$*» (expected fail)" + fi +} diff --git a/test/test_mass_bug b/test/test_mass_bug new file mode 100755 index 0000000..b75386c --- /dev/null +++ b/test/test_mass_bug @@ -0,0 +1,161 @@ +#!/usr/bin/perl + +# Copyright 2020 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 File::Temp qw(tempdir); +use IPC::Run qw(run); +use Test::More; + +# Disable l10n: we look for specific messages +$ENV{LC_ALL} = 'C.UTF-8'; + +my $srcdir = getcwd; +my $top_srcdir = getcwd . '/..'; +my $mass_bug = "$top_srcdir/scripts/mass-bug.pl"; + +if (defined $ARGV[0] && $ARGV[0] eq '--installed') { + $mass_bug = 'mass-bug'; +} + +my $tmp = tempdir(CLEANUP => 1); + +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; +} + +my $stdout; +my $stderr; + +diag('Help'); +$stdout = capture([ + $mass_bug, + '--help', +]); +like($stdout, qr{Usage:}); + +diag('Version'); +$stdout = capture([ + $mass_bug, + '--version', +]); +like($stdout, qr{devscripts package}); + +diag('Basic use'); +$stdout = capture([ + $mass_bug, + '--no-conf', + '--subject=Is broken', + "$srcdir/mass-bug/template", + "$srcdir/mass-bug/one-package", +]); +like($stdout, qr{^Subject: test-package: Is broken$}m); +like($stdout, qr{^Package: test-package$}m); +like($stdout, qr{^Version: 1\.2-3$}m); +like($stdout, qr{^test-package has a bug\. Please fix\.$}m); +like($stdout, qr{^This long line gets word-wrapped because}m); +unlike($stdout, qr{text/plain; format=flowed never really took off\.$}m); +like($stdout, qr{^These short lines also get wrapped\.$}m); +like($stdout, qr{^test-package version=1\.2-3$}m); +like($stdout, qr{^test-package epoch=$}m); +like($stdout, qr{^test-package upstream=1\.2$}m); +like($stdout, qr{^test-package revision=-3$}m); +like($stdout, qr{^test-package reassembled=1\.2-3$}m); +like($stdout, qr{^-- $}m); +like($stdout, qr{^This signature does not get word-wrapped because it is a signature, even though it is longer than a line ought to be\.$}m); + +diag('Subject is mandatory'); +ok(! verbose_run([ + $mass_bug, + '--no-conf', + "$srcdir/mass-bug/template", + "$srcdir/mass-bug/one-package", +], '>', \$stdout, '2>', \$stderr)); +isnt($?, 0); +like($stderr, qr{You must specify a subject}m); +is($stdout, ''); + +diag('Various options'); +$stdout = capture([ + $mass_bug, + '--no-conf', + '--subject=Is broken', + '--source', + '--tags=ftbfs sid', + '--user=me@example.com', + '--usertags=bad wrong', + '--control=block 123456 by -1', + '--control=block -1 by 789012', + '--no-wrap', + "$srcdir/mass-bug/template", + "$srcdir/mass-bug/one-package", +]); +like($stdout, qr{^Subject: test-package: Is broken$}m); +like($stdout, qr{^Source: test-package$}m); +unlike($stdout, qr{^Package: test-package$}m); +like($stdout, qr{^test-package has a bug\. Please fix\.$}m); +like($stdout, qr{^Tags: ftbfs sid$}m); +like($stdout, qr{^User: me\@example\.com$}m); +like($stdout, qr{^Usertags: bad wrong$}m); +like($stdout, qr{^Control: block 123456 by -1$}m); +like($stdout, qr{^Control: block -1 by 789012$}m); +like($stdout, qr{^This long line gets word-wrapped because text/plain; format=flowed never really took off\.$}m); +unlike($stdout, qr{^These short lines also get wrapped\.$}m); + +diag('Version numbers'); +$stdout = capture([ + $mass_bug, + '--no-conf', + '--subject=Is broken', + "$srcdir/mass-bug/template", + "$srcdir/mass-bug/packages", +]); +like($stdout, qr{^native-package version=1\.0$}m); +like($stdout, qr{^native-package epoch=$}m); +like($stdout, qr{^native-package upstream=1\.0$}m); +like($stdout, qr{^native-package revision=$}m); +like($stdout, qr{^native-package reassembled=1\.0$}m); +like($stdout, qr{^upstream-package version=1\.2-3$}m); +like($stdout, qr{^upstream-package epoch=$}m); +like($stdout, qr{^upstream-package upstream=1\.2$}m); +like($stdout, qr{^upstream-package revision=-3$}m); +like($stdout, qr{^upstream-package reassembled=1\.2-3$}m); +like($stdout, qr{^epoch-native-package version=1:2\.3$}m); +like($stdout, qr{^epoch-native-package epoch=1:$}m); +like($stdout, qr{^epoch-native-package upstream=2\.3$}m); +like($stdout, qr{^epoch-native-package revision=$}m); +like($stdout, qr{^epoch-native-package reassembled=1:2\.3$}m); +like($stdout, qr{^epoch-package version=1:2\.3-4\.5$}m); +like($stdout, qr{^epoch-package epoch=1:$}m); +like($stdout, qr{^epoch-package upstream=2\.3$}m); +like($stdout, qr{^epoch-package revision=-4\.5$}m); +like($stdout, qr{^epoch-package reassembled=1:2\.3-4\.5$}m); + +done_testing; 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: diff --git a/test/test_mk-origtargz b/test/test_mk-origtargz new file mode 100755 index 0000000..1aa8f1e --- /dev/null +++ b/test/test_mk-origtargz @@ -0,0 +1,750 @@ +#!/bin/bash + +# Copyright 2014, Rafael Laboissiere <rafael@laboissiere.net> +# Copyright 2015, James McCoy <jamessan@debian.org> + +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u + +# Load GPG +TESTTYPE=MkOrigTarGz +. ./lib_test_uscan + +if test "${1:-}" = --installed; then + MK_ORIGTARGZ="mk-origtargz" + shift +else + top_srcdir=$(readlink -f "${0%/*}/..") + make -C "$top_srcdir/scripts" mk-origtargz + MK_ORIGTARGZ="perl -I $top_srcdir/lib $top_srcdir/scripts/mk-origtargz" + PATH="$top_srcdir/scripts:$PATH" + export PATH + PERL5LIB="$top_srcdir/lib" + export PERL5LIB +fi +PROGNAME="mk-origtargz" + +LC_ALL=C +export LC_ALL + +setUp () { + TMPDIR=$(mktemp -d -p "$SHUNIT_TMPDIR" test_mk-origtargz.XXXX) +} + + +makeSubDir () { + dir=$1 + shift + + mkdir -p "$TMPDIR/foo-0.1/$dir" + touch "$TMPDIR/foo-0.1/$dir/a-file" + mkdir "$TMPDIR/foo-0.1/$dir/a-subdir" + touch "$TMPDIR/foo-0.1/$dir/a-subdir/a-file" +} + + +makeUpstreamFiles () { + mkdir -p "$TMPDIR/foo-0.1" + touch "$TMPDIR/foo-0.1/include-this-file" + touch "$TMPDIR/foo-0.1/exclude-this-file" + touch "$TMPDIR/foo-0.1/.include-this-hidden-file" + touch "$TMPDIR/foo-0.1/.exclude-this-hidden-file" + + makeSubDir "include-this-dir" + makeSubDir "exclude-this-dir" + makeSubDir "exclude-dir1" + makeSubDir "exclude-dir2" + makeSubDir ".include-this-hidden-dir" + makeSubDir ".exclude-this-hidden-dir" + makeSubDir "a-dir/include-this-subdir" + # Expected not to be removed since exclusion is anchored to top-level + makeSubDir "a-dir/exclude-this-subdir" + + touch "$TMPDIR/foo-0.1/; echo strange-file; #" + +} + +makeGolangLikeVendorFiles() { + makeSubDir "vendor" + + mkdir -p "$TMPDIR/foo-0.1/vendor/includeme" + touch "$TMPDIR/foo-0.1/vendor/includeme/important.go" +} + +makeTarBall () { + comp="$1" + mkgpg="${2:-none}" + makeUpstreamFiles + COMP="--auto-compress" + if [ "$comp" = "zst" ]; then + COMP=--zstd + fi + tar --create $COMP --file "$TMPDIR/foo-0.1.tar.$comp" --directory "$TMPDIR" foo-0.1 + local gpgopts=( + chronic_sh $GPG + --homedir "$GPGHOME" + --no-options -q --batch --no-default-keyring + --secret-keyring "$PRIVATE_KEYRING" + --default-key 72544FAF + --detach-sign + ) + case "$mkgpg" in + sig) + "${gpgopts[@]}" "$TMPDIR/foo-0.1.tar.$comp" + ;; + asc) + "${gpgopts[@]}" --armor "$TMPDIR/foo-0.1.tar.$comp" + ;; + none) + ;; + *) + fail "unknown parameter in makeTarBall()" + ;; + esac + rm -rf "$TMPDIR/foo-0.1" +} +makeSimpleTar () { + makeUpstreamFiles + tar --create --file "$TMPDIR/foo-0.1.tar" --directory "$TMPDIR" foo-0.1 + rm -rf "$TMPDIR/foo-0.1" +} +makeBrokenTarBall () { + echo foo > foo.txt + tar cf - foo.txt | sed -e 's/^/foo/' | gzip > "$TMPDIR/foo-0.1.tar.gz" + rm -f foo.txt +} + +makeZipFile () { + makeUpstreamFiles + (cd $TMPDIR >/dev/null; zip -q -r "foo-0.1.zip" foo-0.1 ) + rm -rf "$TMPDIR/foo-0.1" +} + +makeJarFile () { + makeUpstreamFiles + cat > "$TMPDIR/MANIFEST.MF" <<END +Manifest-Version: 1.0 +Main-Class: foo.bar +END + (cd $TMPDIR >/dev/null; jar cf "foo-0.1.jar" MANIFEST.MF foo-0.1 ) + rm -rf "$TMPDIR/foo-0.1" "$TMPDIR/MANIFEST.MF" +} + +makeDebianChangelog() { + mkdir -p $TMPDIR/foo/debian + cat <<END > $TMPDIR/foo/debian/changelog +foo (0.1-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END +} + +makeDebianOldDir() { + makeDebianChangelog +} + +makeDebianDir() { + makeDebianChangelog + mkdir -p $TMPDIR/foo/debian/source + echo -n "3.0 (quilt)" > $TMPDIR/foo/debian/source/format +} + +makeDebianCopyright() { + cat <<'END' > $TMPDIR/foo/debian/copyright +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Files-Excluded: exclude-this* + .exclude-this* + exclude-dir1 + exclude-dir2/ + ;?echo?strange-file;?# +END + +} + +makeWrongDebianCopyright() { + cat <<'END' > $TMPDIR/foo/debian/copyright +Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=174 +Files-Excluded: exclude-this* + .exclude-this* + exclude-dir1 + exclude-dir2/ + ;?echo?strange-file;?# +END + +} + +makeUnmatchedExcludeCopyright() { + cat <<'END' > $TMPDIR/foo/debian/copyright +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Files-Excluded: exclude-this* + .exclude-this* + exclude-dir1 + exclude-dir2 + ;?echo?strange-file;?# + nomatch +END +} + + +makeDuplicatePatternCopyright() { + cat <<'END' > $TMPDIR/foo/debian/copyright +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Files-Excluded: exclude-this* + .exclude-this* + exclude-dir1 + exclude-dir* + ;?echo?strange-file;?# +END +} + +expected_stderr_after_removal="mk-origtargz warn: Files-Excluded pattern (exclude-dir2/) should not have a trailing /" + +expected_files_after_removal=$(LC_ALL=C sort <<END +foo-0.1/ +foo-0.1/a-dir/ +foo-0.1/a-dir/exclude-this-subdir/ +foo-0.1/a-dir/exclude-this-subdir/a-file +foo-0.1/a-dir/exclude-this-subdir/a-subdir/ +foo-0.1/a-dir/exclude-this-subdir/a-subdir/a-file +foo-0.1/a-dir/include-this-subdir/ +foo-0.1/a-dir/include-this-subdir/a-file +foo-0.1/a-dir/include-this-subdir/a-subdir/ +foo-0.1/a-dir/include-this-subdir/a-subdir/a-file +foo-0.1/include-this-dir/ +foo-0.1/include-this-dir/a-file +foo-0.1/include-this-dir/a-subdir/ +foo-0.1/include-this-dir/a-subdir/a-file +foo-0.1/include-this-file +foo-0.1/.include-this-hidden-dir/ +foo-0.1/.include-this-hidden-dir/a-file +foo-0.1/.include-this-hidden-dir/a-subdir/ +foo-0.1/.include-this-hidden-dir/a-subdir/a-file +foo-0.1/.include-this-hidden-file +END +) + +run_mk_origtargz() { + local dir="$1" + local exp_stderr="$2" + local exp_stdout="$3" + local stderrF="${SHUNIT_TMPDIR}/stderr" + shift + shift + shift + output="$( cd $TMPDIR/$dir >/dev/null; LC_ALL=C $MK_ORIGTARGZ "$@" 2> $stderrF )" + stderr="$(cat $stderrF)" + retval=$? + assertEquals "standard output of mk-origtargz $*\n" "$exp_stdout" "$output" + assertEquals "error output of mk-origtargz $*\n" "$exp_stderr" "$stderr" + assertEquals "return valueof mk-origtargz $*\n" "0" "$retval" +} + +assertType () { + mime="$1" + file="$2" + actual="$(file --brief --mime-type "$file" | sed -e 's,/x-,/,')" + assertEquals "filetype for $(basename "$file")" "$mime" "$actual" +} + + +testSymlink() { + makeTarBall gz + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully symlinked ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + ../foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" + assertEquals "final symlink" foo-0.1.tar.gz "$(readlink $TMPDIR/foo_0.1.orig.tar.gz)" +} + +testSymlinkWithConvertedSig() { + makeTarBall gz sig + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully symlinked ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + --signature 1 --signature-file=../foo-0.1.tar.gz.sig \ + ../foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" + assertEquals "final symlink" foo-0.1.tar.gz "$(readlink $TMPDIR/foo_0.1.orig.tar.gz)" + assertTrue "signature isn't valid" "$GPG --homedir '$GPGHOME' --verify $TMPDIR/foo_0.1.orig.tar.gz.asc" +} + +testSymlinkWithArmoredSig() { + # MR for https://lists.debian.org/debian-devel/2019/04/msg00459.html + makeTarBall gz asc + # an armored signature, but with the wrong extension. + mv $TMPDIR/foo-0.1.tar.gz.asc $TMPDIR/foo-0.1.tar.gz.sig + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully symlinked ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + --signature 1 --signature-file=../foo-0.1.tar.gz.sig \ + ../foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" + assertEquals "final symlink" foo-0.1.tar.gz "$(readlink $TMPDIR/foo_0.1.orig.tar.gz)" + assertTrue "signature isn't valid" "$GPG --homedir '$GPGHOME' --verify $TMPDIR/foo_0.1.orig.tar.gz.asc" +} + +testCopy() { + makeTarBall gz + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully copied ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + --copy ../foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testRename() { + makeTarBall gz + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully renamed ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + --rename ../foo-0.1.tar.gz + assertFalse "original tarball does exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testSymlinkExplicit() { + makeTarBall gz + run_mk_origtargz "" "" \ + "Successfully symlinked foo-0.1.tar.gz to foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" + assertEquals "final symlink" foo-0.1.tar.gz "$(readlink $TMPDIR/foo_0.1.orig.tar.gz)" +} + +testCopyExplicit() { + makeTarBall gz + run_mk_origtargz "" "" \ + "Successfully copied foo-0.1.tar.gz to foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 --copy foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testRenameExplicit() { + makeTarBall gz + run_mk_origtargz "" "" \ + "Successfully renamed foo-0.1.tar.gz to foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 --rename foo-0.1.tar.gz + assertFalse "original tarball does exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testSymlinkExplicitSubdir() { + makeTarBall gz + mkdir -p $TMPDIR/destdir + run_mk_origtargz "" "" \ + "Successfully symlinked foo-0.1.tar.gz to destdir/foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 -C destdir foo-0.1.tar.gz + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/destdir/foo_0.1.orig.tar.gz ]" + assertTrue "result is not a symlink" "[ -L $TMPDIR/destdir/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/destdir/foo_0.1.orig.tar.gz ]" + assertEquals "final symlink" ../foo-0.1.tar.gz "$(readlink $TMPDIR/destdir/foo_0.1.orig.tar.gz)" +} + +testRepackGZ2GZ() { + makeTarBall gz + run_mk_origtargz "" "" \ + "Successfully copied foo-0.1.tar.gz to foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 --copy foo-0.1.tar.gz --repack --compression gzip + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertType application/gzip $TMPDIR/foo_0.1.orig.tar.gz +} + +testForceRepackGZ2XZ() { + makeTarBall gz + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully repacked ../foo-0.1.tar.gz as ../foo_0.1.orig.tar.gz." \ + --force-repack ../foo-0.1.tar.gz --compression gzip + assertTrue "original tarball does not exist" "[ -e $TMPDIR/foo-0.1.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not a file" "[ -f $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result is not readable" "[ -r $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testRepackGZ2XZ() { + makeTarBall gz + run_mk_origtargz "" ""\ + "Successfully repacked foo-0.1.tar.gz as foo_0.1.orig.tar.xz." \ + --package foo --version 0.1 --copy foo-0.1.tar.gz --repack + assertFalse "wrong result does exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz +} + +testRepackXZ2GZ() { + makeTarBall xz + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.tar.xz as foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 --copy foo-0.1.tar.xz --repack --compression gzip + assertFalse "wrong result does exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertType application/gzip $TMPDIR/foo_0.1.orig.tar.gz +} + +testRepackZST2XZRepackOpt() { + makeTarBall zst + run_mk_origtargz "" ""\ + "Successfully repacked foo-0.1.tar.zst as foo_0.1.orig.tar.xz." \ + --package foo --version 0.1 --copy foo-0.1.tar.zst --repack + assertFalse "wrong result does exist" "[ -e $TMPDIR/foo_0.1.orig.tar.zst ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz +} + +testRepackZST2XZNoRepackOpt() { + makeTarBall zst + run_mk_origtargz "" ""\ + "Successfully repacked foo-0.1.tar.zst as foo_0.1.orig.tar.xz." \ + --package foo --version 0.1 --copy foo-0.1.tar.zst + assertFalse "wrong result does exist" "[ -e $TMPDIR/foo_0.1.orig.tar.zst ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz +} + +testRepackZST2ZSTFail() { + makeTarBall zst + run_mk_origtargz "" "mk-origtargz error: Bad value for compression: Unknown compression scheme zst"\ + "" \ + --package foo --version 0.1 --copy foo-0.1.tar.zst --compression zst + assertFalse "wrong result does exist" "[ -e $TMPDIR/foo_0.1.orig.tar.zst ]" + assertFalse "result does exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" +} + +testRepackZip2GZ() { + makeZipFile + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.zip as foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 --copy foo-0.1.zip --compression gzip + assertTrue "original zip file does not exist" "[ -e $TMPDIR/foo-0.1.zip ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertType application/gzip $TMPDIR/foo_0.1.orig.tar.gz +} + +testRepackJar2GZ() { + if ! command -v jar >/dev/null + then + # skip to avoid dependency on java-jdk + return + fi + makeJarFile + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.jar as foo_0.1.orig.tar.gz." \ + --package foo --version 0.1 --copy foo-0.1.jar --compression gzip + assertTrue "original zip file does not exist" "[ -e $TMPDIR/foo-0.1.jar ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertType application/gzip $TMPDIR/foo_0.1.orig.tar.gz +} + +testRepackZip2GZRename() { + makeZipFile + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.zip as foo_0.1.orig.tar.gz, and removed the original file." \ + --package foo --version 0.1 --rename foo-0.1.zip --compression gzip + assertFalse "original zip file does exist" "[ -e $TMPDIR/foo-0.1.zip ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertType application/gzip $TMPDIR/foo_0.1.orig.tar.gz +} + +testRepackZip2XZ() { + makeZipFile + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.zip as foo_0.1.orig.tar.xz." \ + --package foo --version 0.1 foo-0.1.zip + assertTrue "original zip file does not exist" "[ -e $TMPDIR/foo-0.1.zip ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz +} + +testRepackXpi2XZ() { + makeZipFile + mv $TMPDIR/foo-0.1.zip $TMPDIR/foo-0.1.xpi + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.xpi as foo_0.1.orig.tar.xz." \ + --package foo --version 0.1 foo-0.1.xpi + assertTrue "original xpi file does not exist" "[ -e $TMPDIR/foo-0.1.xpi ]" + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz +} + +testRepackTAR2XZ() { + makeSimpleTar + run_mk_origtargz "" "" \ + "Successfully repacked foo-0.1.tar as foo_0.1.orig.tar.xz." \ + --package foo --version 0.1 --copy foo-0.1.tar --repack + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz +} +testOldFormat() { + makeTarBall xz + makeDebianOldDir + makeDebianCopyright + run_mk_origtargz foo "mk-origtargz warn: Missing debian/source/format, switch compression to gzip +$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.tar.xz as ../foo_0.1.orig.tar.gz, deleting 19 files from it." \ + ../foo-0.1.tar.xz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertType application/gzip $TMPDIR/foo_0.1.orig.tar.gz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.gz | sort)" +} + +testExclude() { + makeTarBall gz + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.tar.gz as ../foo_0.1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +testGoVendorIncludeIgnore () { + makeGolangLikeVendorFiles + makeTarBall gz + makeDebianDir + makeDebianCopyright + + # adjust existing test cases slightly + cat <<'END' >> $TMPDIR/foo/debian/copyright + vendor +Files-Included: + vendor/includeme +END + + expected_files=$(LC_ALL=C sort <<END +$expected_files_after_removal +foo-0.1/vendor/ +foo-0.1/vendor/a-subdir/ +foo-0.1/vendor/includeme/ +foo-0.1/vendor/includeme/important.go +END +) + + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.tar.gz as ../foo_0.1.orig.tar.xz, deleting 21 files from it." \ + ../foo-0.1.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz + assertEquals "file contents" "$expected_files" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +testExcludeXZ() { + makeTarBall xz + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.tar.xz as ../foo_0.1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.tar.xz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +testExcludeZip() { + makeZipFile + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.zip as ../foo_0.1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.zip + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +testSuffix() { + makeTarBall gz + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.tar.gz as ../foo_0.1+dfsg1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.tar.gz --repack-suffix +dfsg1 + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1+dfsg1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1+dfsg1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1+dfsg1.orig.tar.xz | sort)" +} + +testSuffixXZ() { + makeTarBall xz + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.tar.xz as ../foo_0.1+dfsg1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.tar.xz --repack-suffix +dfsg1 + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1+dfsg1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1+dfsg1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1+dfsg1.orig.tar.xz | sort)" +} + +testSuffixZip() { + makeZipFile + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Successfully repacked ../foo-0.1.zip as ../foo_0.1+dfsg1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.zip --repack-suffix +dfsg1 + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1+dfsg1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1+dfsg1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1+dfsg1.orig.tar.xz | sort)" +} + +testSuffixNoExclusions() { + makeTarBall gz + makeDebianDir + run_mk_origtargz foo "" \ + "Successfully renamed ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + ../foo-0.1.tar.gz --rename --repack-suffix +dfsg1 + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testSameNameSymlink() { + makeTarBall gz + mv $TMPDIR/foo-0.1.tar.gz $TMPDIR/foo_0.1.orig.tar.gz + makeDebianDir + run_mk_origtargz foo "" \ + "Leaving ../foo_0.1.orig.tar.gz where it is." \ + --symlink ../foo_0.1.orig.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testSameNameCopy() { + makeTarBall gz + mv $TMPDIR/foo-0.1.tar.gz $TMPDIR/foo_0.1.orig.tar.gz + makeDebianDir + run_mk_origtargz foo "" \ + "Leaving ../foo_0.1.orig.tar.gz where it is." \ + --copy ../foo_0.1.orig.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testSameNameRename() { + makeTarBall gz + mv $TMPDIR/foo-0.1.tar.gz $TMPDIR/foo_0.1.orig.tar.gz + makeDebianDir + run_mk_origtargz foo "" \ + "Leaving ../foo_0.1.orig.tar.gz where it is." \ + --rename ../foo_0.1.orig.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" +} + +testSameNameExclude() { + makeTarBall gz + mv $TMPDIR/foo-0.1.tar.gz $TMPDIR/foo_0.1.orig.tar.gz + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Leaving ../foo_0.1.orig.tar.gz where it is, deleting 19 files from it." \ + ../foo_0.1.orig.tar.gz --compression=gzip + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.gz ]" + assertFalse "result is a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.gz ]" + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.gz | sort)" +} + +testSameNameExcludeSymlink() { + makeTarBall xz + ln -s foo-0.1.tar.xz $TMPDIR/foo_0.1.orig.tar.xz + makeDebianDir + makeDebianCopyright + run_mk_origtargz foo "$expected_stderr_after_removal" \ + "Leaving ../foo_0.1.orig.tar.xz where it is, deleting 19 files from it." \ + ../foo_0.1.orig.tar.xz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertTrue "result is not a symlink" "[ -L $TMPDIR/foo_0.1.orig.tar.xz ]" + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +testCopyrightFormatWarning() { + makeTarBall gz + makeDebianDir + makeWrongDebianCopyright + run_mk_origtargz foo \ + "mk-origtargz warn: The file debian/copyright mentions Files-Excluded, but its format is not recognized. Specify Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ in order to remove files from the tarball with mk-origtargz." \ + "Successfully symlinked ../foo-0.1.tar.gz to ../foo_0.1.orig.tar.gz." \ + ../foo-0.1.tar.gz + +} + +testBrokenTarWarning() { + makeBrokenTarBall + makeDebianDir + if dpkg --compare-versions $(dpkg-query -W -f='${Version}' libdpkg-perl) lt 1.19.0~; then + local SUBPROCESS_ERROR="gave error exit status 2" + else + local SUBPROCESS_ERROR="subprocess returned exit status 2" + fi + run_mk_origtargz foo \ + "tar: This does not look like a tar archive +tar: Skipping to next header +tar: Exiting with failure status due to previous errors +$PROGNAME: error: tar --list --auto-compress --file ../foo_0.1.orig.tar.xz $SUBPROCESS_ERROR" \ + "" \ + ../foo-0.1.tar.gz --repack +} + +testUnmatchedExclusion() { + makeTarBall gz + makeDebianDir + makeUnmatchedExcludeCopyright + run_mk_origtargz foo "mk-origtargz warn: No files matched excluded pattern as the last matching glob: nomatch" \ + "Successfully repacked ../foo-0.1.tar.gz as ../foo_0.1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +testDuplicatePattern() { + makeTarBall gz + makeDebianDir + makeDuplicatePatternCopyright + run_mk_origtargz foo "mk-origtargz warn: No files matched excluded pattern as the last matching glob: exclude-dir1" \ + "Successfully repacked ../foo-0.1.tar.gz as ../foo_0.1.orig.tar.xz, deleting 19 files from it." \ + ../foo-0.1.tar.gz + assertTrue "result does not exist" "[ -e $TMPDIR/foo_0.1.orig.tar.xz ]" + assertType application/xz $TMPDIR/foo_0.1.orig.tar.xz + assertEquals "file contents" "$expected_files_after_removal" "$(tar taf $TMPDIR/foo_0.1.orig.tar.xz | sort)" +} + +. shunit2 diff --git a/test/test_package_lifecycle b/test/test_package_lifecycle new file mode 100755 index 0000000..9ed7485 --- /dev/null +++ b/test/test_package_lifecycle @@ -0,0 +1,386 @@ +#!/bin/bash + +# Copyright (C) 2015, Nicholas Bamber <nicholas@periapt.co.uk> +# +# 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/>. + +set -u + +WORKDIR=$(readlink -f "${0%/*}") +_ARCH=$(dpkg-architecture -qDEB_BUILD_ARCH) +declare -r _ARCH +if dpkg --compare-versions "$(dpkg-query -W -f='${Version}' dpkg-dev )" lt "1.19.1~"; then + echo "This test requires dpkg-dev >= 1.19.1." >&2 + exit 1 +fi +if dpkg --compare-versions "$(dpkg-query -W -f='${Version}' dpkg-dev )" lt "1.21.0~"; then + _dpkg_genchanges="dpkg-genchanges >" +elif dpkg --compare-versions "$(dpkg-query -W -f='${Version}' dpkg-dev )" eq "1.21.0"; then + echo "This version of dpkg produces incorrect output, not supported" >&2 + exit 1 +else + _dpkg_genchanges="dpkg-genchanges -O" +fi +declare -r _dpkg_genchanges + +if test "${1:-}" = --installed; then + shift +else + PATH=${WORKDIR}/../scripts:${PATH} + PERL5LIB=${WORKDIR}/../lib:${PERL5LIB:-} + export PATH PERL5LIB +fi + +. "${0%/*}/shunit2-helper-functions.sh" + +GPGHOME=$(mktemp -d -p /tmp gpg.XXXXX) + +oneTimeSetUp () { + GPG=gpg + if ! command -v $GPG >/dev/null 2>&1;then + echo "$GPG missing" + GPG=gpg2 + if ! command -v $GPG >/dev/null 2>&1;then + echo "$GPG missing" + exit 1 + fi + fi + + PRIVATE_KEY=${WORKDIR}/uscan/PRIVATE_KEY.asc + PUBLIC_KEY=${WORKDIR}/uscan/PUBLIC_KEY.asc + + PRIVATE_KEYRING=$GPGHOME/secring.gpg + PUBLIC_KEYRING=$GPGHOME/pubring.gpg + + $GPG -v --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --output $PRIVATE_KEYRING --dearmor $PRIVATE_KEY + + $GPG -v --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --output $PUBLIC_KEYRING --dearmor $PUBLIC_KEY + + $GPG --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --secret-keyring $PRIVATE_KEYRING --default-key 72543FAF \ + --list-keys --verbose + + mkdir -p ${WORKDIR}/package_lifecycle/test/debian/source + cat > ${WORKDIR}/package_lifecycle/test/debian/control <<-EOS + Source: test + Section: devel + Priority: optional + Maintainer: Devscripts Devel Team <devscripts-devel@lists.alioth.debian.org> + Uploaders: Testophilus Testownik <tester@testity.org> + Standards-Version: 4.5.0 + Rules-Requires-Root: no + + Package: test + Architecture: all + Description: Short description + Longer description +EOS + printf '#!/usr/bin/make -f\n%%:\n\tdh $@' > ${WORKDIR}/package_lifecycle/test/debian/rules + chmod +x ${WORKDIR}/package_lifecycle/test/debian/rules + _DATE=$(LC_ALL=C date '+%a, %d %b %Y %T +0000') + cat > ${WORKDIR}/package_lifecycle/test/debian/changelog <<-EOS + test (1.0-1) unstable; urgency=low + + * Initial packaging + + -- Testophilus Testownik <tester@testity.org> ${_DATE} +EOS + echo 12 > ${WORKDIR}/package_lifecycle/test/debian/compat + echo '3.0 (quilt)' > ${WORKDIR}/package_lifecycle/test/debian/source/format + touch ${WORKDIR}/package_lifecycle/test/CONTENTS + cd ${WORKDIR}/package_lifecycle/ && tar cvf test_1.0.orig.tar --exclude debian -- test/CONTENTS 2>&1 > /dev/null && xz -f test_1.0.orig.tar + cd ${WORKDIR} +} + +runCommandOutCmpFile() { + local param="$1" + local exp_stdoutfile="$2" + local exp_stderr="$3" + local exp_retval=$4 + local stdoutF="${SHUNIT_TMPDIR}/stdout" + local stderrF="${SHUNIT_TMPDIR}/stderr" + eval "${COMMAND} $param" 2> ${stderrF} | \ + grep -v File::FcntlLock | \ + grep -v '^ *dh_' | \ + grep -v '^dh_gencontrol debug symbol wrapper:' | \ + grep -v '^ *create-stamp debian/debhelper' | \ + sed -e "s/\`/'/g" | \ + sed -e "s/^dpkg-buildpackage: info: /dpkg-buildpackage: /g" | \ + sed -e "s/^dpkg-genchanges: info: /dpkg-genchanges: /g" | \ + sed -e "/^ dpkg-genbuildinfo/d" | \ + sed -e "/^gpg: /d" | \ + sed -e's!^ -- Testophilus Testownik <tester@testity.org>.*! -- Testophilus Testownik <tester@testity.org>!' > ${stdoutF} + retval=$? + eval "cmp ${stdoutF} ${exp_stdoutfile}" 3>&1 >/dev/null + local diffretval=$? + assertEquals "standard output of ${COMMAND} $param matches ${exp_stdoutfile}\n" "0" "$diffretval" || diff ${stdoutF} ${exp_stdoutfile} + assertEquals "error output of ${COMMAND} $param\n" "$exp_stderr" "$(cat ${stderrF})" + assertEquals "return value of ${COMMAND} $param\n" $exp_retval $retval +} + + +test_debuild() { + export GNUPGHOME=$GPGHOME + cd ${WORKDIR}/package_lifecycle/test + COMMAND='LC_ALL=C debuild --no-conf --no-lintian --preserve-envvar=PATH --preserve-envvar=PERL5LIB --preserve-envvar=DEBFULLNAME --preserve-envvar=DEBEMAIL --preserve-envvar=GNUPGHOME --set-envvar=NO_PKG_MANGLE=1' + cat > ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + dpkg-buildpackage -us -uc -ui + dpkg-buildpackage: source package test + dpkg-buildpackage: source version 1.0-1 + dpkg-buildpackage: source distribution unstable + dpkg-buildpackage: source changed by Testophilus Testownik <tester@testity.org> + dpkg-source --before-build . + dpkg-buildpackage: host architecture ${_ARCH} + debian/rules clean + dh clean + dpkg-source -b . + dpkg-source: info: using source format '3.0 (quilt)' + dpkg-source: info: building test using existing ./test_1.0.orig.tar.xz + dpkg-source: info: building test in test_1.0-1.debian.tar.xz + dpkg-source: info: building test in test_1.0-1.dsc + debian/rules binary + dh binary + dpkg-deb: building package 'test' in '../test_1.0-1_all.deb'. + ${_dpkg_genchanges}../test_1.0-1_${_ARCH}.changes + dpkg-genchanges: including full source code in upload + dpkg-source --after-build . + dpkg-buildpackage: full upload (original source is included) + Now signing changes and any dsc files... +EOS + if command -v dpkg-genbuildinfo >/dev/null; then + cat >> ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + signfile dsc test_1.0-1.dsc uscan test key (no secret) <none@debian.org> + + fixup_buildinfo test_1.0-1.dsc test_1.0-1_${_ARCH}.buildinfo + signfile buildinfo test_1.0-1_${_ARCH}.buildinfo uscan test key (no secret) <none@debian.org> + + fixup_changes dsc test_1.0-1.dsc test_1.0-1_${_ARCH}.changes + fixup_changes buildinfo test_1.0-1_${_ARCH}.buildinfo test_1.0-1_${_ARCH}.changes + signfile changes test_1.0-1_${_ARCH}.changes uscan test key (no secret) <none@debian.org> + + Successfully signed dsc, buildinfo, changes files +EOS + else + cat >> ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + signfile dsc test_1.0-1.dsc uscan test key (no secret) <none@debian.org> + + fixup_changes dsc test_1.0-1.dsc test_1.0-1_${_ARCH}.changes + signfile changes test_1.0-1_${_ARCH}.changes uscan test key (no secret) <none@debian.org> + + Successfully signed dsc, changes files +EOS + fi + runCommandOutCmpFile "-k'uscan test key (no secret) <none@debian.org>'" "${WORKDIR}/package_lifecycle/debuild.txt" "" 0 + cd ${WORKDIR} +} + +test_dscverify () { + cd ${WORKDIR}/package_lifecycle + COMMAND='dscverify --no-conf --keyring $GPGHOME/pubring.gpg' + cat > ${WORKDIR}/package_lifecycle/dscverify.txt <<-EOS + ${WORKDIR}/package_lifecycle/test_1.0-1.dsc: + Good signature found + validating test_1.0.orig.tar.xz + validating test_1.0-1.debian.tar.xz + All files validated successfully. +EOS + runCommandOutCmpFile "${WORKDIR}/package_lifecycle/test_1.0-1.dsc" "${WORKDIR}/package_lifecycle/dscverify.txt" "" 0 + cd ${WORKDIR} +} + +test_dscextractControl () { + cd ${WORKDIR}/package_lifecycle + COMMAND='dscextract' + cat > ${WORKDIR}/package_lifecycle/dscextractControl.txt <<-EOS + Source: test + Section: devel + Priority: optional + Maintainer: Devscripts Devel Team <devscripts-devel@lists.alioth.debian.org> + Uploaders: Testophilus Testownik <tester@testity.org> + Standards-Version: 4.5.0 + Rules-Requires-Root: no + + Package: test + Architecture: all + Description: Short description + Longer description +EOS + runCommandOutCmpFile "test_1.0-1.dsc debian/control" "dscextractControl.txt" "" 0 + cd ${WORKDIR} +} + +test_dscextractChangelog () { + cd ${WORKDIR}/package_lifecycle + COMMAND='dscextract' + cat > ${WORKDIR}/package_lifecycle/dscextractChangelog.txt <<-EOS + test (1.0-1) unstable; urgency=low + + * Initial packaging + + -- Testophilus Testownik <tester@testity.org> +EOS + runCommandOutCmpFile "test_1.0-1.dsc debian/changelog" "dscextractChangelog.txt" "" 0 + cd ${WORKDIR} +} + +test_debchange () { + cd ${WORKDIR}/package_lifecycle/test + COMMAND='debchange' + export DEBFULLNAME='Testophilus Testownik' + export DEBEMAIL='tester@testity.org' + cat > ${WORKDIR}/package_lifecycle/debchange.txt <<-EOS + test (1.0-2) UNRELEASED; urgency=medium + + * new killer app functionality + + -- Testophilus Testownik <tester@testity.org> + + test (1.0-1) unstable; urgency=low + + * Initial packaging + + -- Testophilus Testownik <tester@testity.org> +EOS + runCommand "-iU 'new killer app functionality'" "" "" 0 + COMMAND=cat + runCommandOutCmpFile "debian/changelog" "../debchange.txt" "" 0 + cd ${WORKDIR} +} + +test_list_unreleased () { + cd ${WORKDIR}/package_lifecycle/test + COMMAND='list-unreleased' + cat > ${WORKDIR}/package_lifecycle/list-unreleased.txt <<-EOS + test (1.0-2) UNRELEASED; urgency=medium + + * new killer app functionality + + -- Testophilus Testownik <tester@testity.org> +EOS + runCommandOutCmpFile "-c -R" "../list-unreleased.txt" "" 0 + cd ${WORKDIR} +} + + +test_debuild2() { + export GNUPGHOME=$GPGHOME + cd ${WORKDIR}/package_lifecycle/test + COMMAND='LC_ALL=C debuild --no-conf --no-lintian --preserve-envvar=PATH --preserve-envvar=PERL5LIB --preserve-envvar=DEBFULLNAME --preserve-envvar=DEBEMAIL --preserve-envvar=GNUPGHOME --set-envvar=NO_PKG_MANGLE=1' + cat > ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + dpkg-buildpackage -us -uc -ui + dpkg-buildpackage: source package test + dpkg-buildpackage: source version 1.0-2 + dpkg-buildpackage: source distribution UNRELEASED + dpkg-buildpackage: source changed by Testophilus Testownik <tester@testity.org> + dpkg-source --before-build . + dpkg-buildpackage: host architecture ${_ARCH} + debian/rules clean + dh clean + dpkg-source -b . + dpkg-source: info: using source format '3.0 (quilt)' + dpkg-source: info: building test using existing ./test_1.0.orig.tar.xz + dpkg-source: info: building test in test_1.0-2.debian.tar.xz + dpkg-source: info: building test in test_1.0-2.dsc + debian/rules binary + dh binary + dpkg-deb: building package 'test' in '../test_1.0-2_all.deb'. + ${_dpkg_genchanges}../test_1.0-2_${_ARCH}.changes + dpkg-genchanges: not including original source code in upload + dpkg-source --after-build . + dpkg-buildpackage: binary and diff upload (original source NOT included) +EOS + runCommandOutCmpFile "-k'uscan test key (no secret) <none@debian.org>'" "${WORKDIR}/package_lifecycle/debuild.txt" "" 0 + cd ${WORKDIR} +} + +test_debuild_forcesign() { + export GNUPGHOME=$GPGHOME + cd ${WORKDIR}/package_lifecycle/test + COMMAND='LC_ALL=C debuild --no-conf --no-lintian --preserve-envvar=PATH --preserve-envvar=PERL5LIB --preserve-envvar=DEBFULLNAME --preserve-envvar=DEBEMAIL --preserve-envvar=GNUPGHOME --set-envvar=NO_PKG_MANGLE=1 --force-sign' + cat > ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + dpkg-buildpackage -us -uc -ui + dpkg-buildpackage: source package test + dpkg-buildpackage: source version 1.0-2 + dpkg-buildpackage: source distribution UNRELEASED + dpkg-buildpackage: source changed by Testophilus Testownik <tester@testity.org> + dpkg-source --before-build . + dpkg-buildpackage: host architecture ${_ARCH} + debian/rules clean + dh clean + dpkg-source -b . + dpkg-source: info: using source format '3.0 (quilt)' + dpkg-source: info: building test using existing ./test_1.0.orig.tar.xz + dpkg-source: info: building test in test_1.0-2.debian.tar.xz + dpkg-source: info: building test in test_1.0-2.dsc + debian/rules binary + dh binary + dpkg-deb: building package 'test' in '../test_1.0-2_all.deb'. + ${_dpkg_genchanges}../test_1.0-2_${_ARCH}.changes + dpkg-genchanges: not including original source code in upload + dpkg-source --after-build . + dpkg-buildpackage: binary and diff upload (original source NOT included) + Now signing changes and any dsc files... +EOS + if command -v dpkg-genbuildinfo >/dev/null; then + cat >> ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + signfile dsc test_1.0-2.dsc uscan test key (no secret) <none@debian.org> + + fixup_buildinfo test_1.0-2.dsc test_1.0-2_${_ARCH}.buildinfo + signfile buildinfo test_1.0-2_${_ARCH}.buildinfo uscan test key (no secret) <none@debian.org> + + fixup_changes dsc test_1.0-2.dsc test_1.0-2_${_ARCH}.changes + fixup_changes buildinfo test_1.0-2_${_ARCH}.buildinfo test_1.0-2_${_ARCH}.changes + signfile changes test_1.0-2_${_ARCH}.changes uscan test key (no secret) <none@debian.org> + + Successfully signed dsc, buildinfo, changes files +EOS + else + cat >> ${WORKDIR}/package_lifecycle/debuild.txt <<-EOS + signfile dsc test_1.0-2.dsc uscan test key (no secret) <none@debian.org> + + fixup_changes dsc test_1.0-2.dsc test_1.0-2_${_ARCH}.changes + signfile changes test_1.0-2_${_ARCH}.changes uscan test key (no secret) <none@debian.org> + + Successfully signed dsc, changes files +EOS + fi + runCommandOutCmpFile "-k'uscan test key (no secret) <none@debian.org>'" "${WORKDIR}/package_lifecycle/debuild.txt" "" 0 + cd ${WORKDIR} +} + +test_debdiff () { + cd ${WORKDIR}/package_lifecycle + COMMAND='debdiff --no-conf' + cat > ${WORKDIR}/package_lifecycle/debdiff.txt <<-EOS + File lists identical (after any substitutions) + + Control files: lines which differ (wdiff format) + ------------------------------------------------ + Version: [-1.0-1-] {+1.0-2+} +EOS + runCommandOutCmpFile "test_1.0-1_${_ARCH}.changes test_1.0-2_${_ARCH}.changes" "debdiff.txt" "" 0 + cd ${WORKDIR} +} + +oneTimeTearDown () { + rm -rf ${WORKDIR}/package_lifecycle + gpgconf --homedir "$GPGHOME" --kill gpg-agent + rm -rf "$GPGHOME" +} + +cd ${WORKDIR} +. shunit2 + diff --git a/test/test_perl b/test/test_perl new file mode 100755 index 0000000..aed1906 --- /dev/null +++ b/test/test_perl @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +LIB=-I../lib +if test "${1:-}" = --installed; then + LIB="" + shift +fi + +prove --norc $LIB t/*.t + diff --git a/test/test_perltidy b/test/test_perltidy new file mode 100755 index 0000000..af9827c --- /dev/null +++ b/test/test_perltidy @@ -0,0 +1,39 @@ +#!/bin/sh + +set -u + +base="$(readlink -f "${0%/*}"/..)" + + +# perltidy test is ran only during dev +if test "$(cd "$base" && dpkg-parsechangelog -c0 -SDistribution)" != UNRELEASED; then + echo "SKIP: Not checking a released version with perltidy." + exit 0 +fi + +# perltidy test isn't ran in autopkgtest environment +if test "${1:-}" = --installed; then + echo "SKIP: Not running perltidy in autopkgtest." + exit 0 +fi + +# Don't run this test with old Perltidy versions +if test "$(perl -MPerl::Tidy -le 'print $Perl::Tidy::VERSION')" -lt 20220613; then + echo "SKIP: perltidy version too old, skipping this test." + exit 0 +fi + + +testPerltidy() { + LIST=$(find "$base/lib/" "$base/scripts/" -iname '*.pl' -or -iname '*.pm') + + for file in $LIST; do + perltidy --output-path="$SHUNIT_TMPDIR/" --profile="$base/.perltidyrc" "$file" + cmp -s "$file" "$SHUNIT_TMPDIR/$(basename "$file").tdy" + retval=$? + assertEquals "## $file isn't following perltidy" 0 "$retval" + done + +} + +. shunit2 diff --git a/test/test_sadt b/test/test_sadt new file mode 100755 index 0000000..0292d20 --- /dev/null +++ b/test/test_sadt @@ -0,0 +1,100 @@ +#!/bin/sh + +# Copyright (C) 2018, Antonio Terceiro <terceiro@debian.org> +# +# 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/>. + +set -u + +. ${0%/*}/test_helper.sh + +if test "${1:-}" = --installed; then + sadt="sadt" + shift +else + sadt="$(readlink -f "${0%/*}/../scripts/sadt")" +fi + +samples="${0%/*}/sadt" + +run_sadt() { + dir="$1" + shift + (cd "$samples/$dir" && $sadt "$@") +} + +test_passes() { + assertPasses run_sadt passes +} + +test_superficial() { + assertPasses run_sadt superficial + assertFails run_sadt superficial-fails +} + +test_flaky() { + assertPasses run_sadt flaky +} + +test_skippable() { + assertPasses run_sadt skippable +} + +test_skippable_fails() { + assertFails run_sadt unskippable + assertFails run_sadt unskipped +} + +test_fails() { + assertFails run_sadt fails +} + +test_space_separated_tests() { + assertPasses run_sadt space-separated-tests + assertFalse "skipped=1 found in output" "grep -q skipped=1 $log" +} + +test_comma_separated_tests() { + assertPasses run_sadt comma-separated-tests + assertFalse "skipped=1 found in output" "grep -q skipped=1 $log" +} + +test_space_separated_restrictions() { + assertPasses run_sadt space-separated-restrictions + assertFalse "skipped=1 found in output" "grep -q skipped=1 $log" +} + +test_comma_separated_restrictions() { + assertPasses run_sadt comma-separated-restrictions + assertFalse "skipped=1 found in output" "grep -q skipped=1 $log" +} + +test_tests_directory() { + assertPasses run_sadt tests-directory + assertFalse "skipped=1 found in output" "grep -q skipped=1 $log" +} + +test_test_command() { + assertPasses run_sadt test-command --verbose + assertTrue "recognizes Test-Command" "grep 'O: Test-Command is supported' $log" + assertTrue "recognizes Test-Command" "grep tests=1 $log" +} + +test_run_specific_tests() { + assertPasses run_sadt comma-separated-tests --verbose test1 + assertTrue "runs test1" "grep '^test1:' $log" + assertFalse "does not run test2" "grep '^test2:' $log" +} + +. shunit2 diff --git a/test/test_salsa b/test/test_salsa new file mode 100755 index 0000000..8c21342 --- /dev/null +++ b/test/test_salsa @@ -0,0 +1,106 @@ +#!/usr/bin/perl + +use strict; +use lib '../lib'; +use Test::More; + +my $skip; + +BEGIN { + my $cwd = `pwd`; + chomp $cwd; + eval "use File::Temp 'tempdir';" + . "use Test::Output;use GitLab::API::v4;" + . "use lib '$cwd/../lib'"; + $skip = $@ ? 1 : 0; +} + +sub run { + my ($result, $out, @list) = @_; + @ARGV = @list; + my $res; + combined_like( + sub { + $res = Devscripts::Salsa->new->run; + }, + $out, + "command: " . join(' ', @list)); + ok($res =~ /^$result$/i, " result is $result"); +} + +sub mkDebianDir { + my $tmpdir = tempdir(CLEANUP => 1); + chdir $tmpdir; + $ENV{"GIT_CONFIG_NOGLOBAL"} = 1; + system "git init"; + mkdir 'debian'; + open F, ">debian/changelog"; + print F <<EOF; +foobar (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd\@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +EOF + close F; + open F, ">README.md"; + print F <<EOF; +# Salsa test +EOF + system "git add *"; + system "git commit -a -m 'Salsa test'"; +} + +SKIP: { + skip "Missing dependencies" if ($skip); + use_ok 'Devscripts::Salsa'; + $Devscripts::Output::die_on_error = 0; + + # Search methods + run(0, qr/Id.*\nUsername.*/s, 'whoami'); + run(0, qr/Id.*\nName/s, 'search_group', 'js-team'); + run(0, qr/Id.*\nName/s, 'search_group', '2666'); + run(0, qr/Id.*\nName/s, 'search_group', 'perl-team/modules'); + run(0, qr/Id.*\nUsername\s*: yadd/s, 'search_user', 'yadd'); + run(0, qr/Id.*\nUsername\s*: yadd/s, 'search_user', 'yad'); + run(0, qr/Id.*\nUsername\s*: yadd/s, 'search_user', '3818'); + run(0, qr/Id.*\nName\s*: qa/s, 'search_project', 'qa'); + run(0, qr/Id.*\nName\s*: qa/s, 'search_project', '1417'); + run(0, qr/Id.*\nName\s*: qa/s, 'search_project', 'qa/qa'); + run(0, qr/Id.*\nUsername.*/s, '--group', 'perl-team', 'group'); + run(0, qr/Id.*\nName/s, '--group', 'perl-team', 'list_repos'); + run(0, qr/Id.*\nName/s, 'list_groups'); + run(0, qr/Id.*\n\tName/s, 'forks', 'qa/qa'); + run(0, qr/^debian\/devscripts/m, 'mrs', 'debian/devscripts'); + run(0, qr/^devscripts/m, 'mrs', 'devscripts', '--group-id', 2); + run(0, qr/master.*Maintainer.*Developers/m, + 'protected_branches', 'debian/devscripts'); + + # checkout + { + my $tmpdir = tempdir(CLEANUP => 1); + run(0, qr/gbp:info/, 'co', '-C', $tmpdir, + 'debian/libapache2-mod-fcgid'); + ok( + -d "$tmpdir/libapache2-mod-fcgid/.git", + ' libapache2-mod-fcgid cloned' + ); + run(0, qr/gbp:info/, 'checkout', '-C', $tmpdir, '--group=qa', 'qa'); + ok(-d "$tmpdir/qa/.git", ' qa cloned'); + } + + # push_repo, update_repo and del_repo + if ($ARGV[0] eq '--full') { + mkDebianDir; + run(0, qr/Project .*created/s, + 'push_repo', '.', '--verbose', '--kgb', '--irc=devscripts'); + diag "Verify that foobar appears in #devscripts channel"; + run(0, qr/Project .*updated/s, + 'update_repo', 'foobar', '--rename-head'); + run(1, qr/update_repo has failed for foobar/s, + 'update_repo', 'foobar', '--rename-head', '--no-fail'); + run(0, qr/Project .*foobar deleted/s, + '--verbose', 'del_repo', 'foobar'); + } +} +done_testing; diff --git a/test/test_uscan b/test/test_uscan new file mode 100755 index 0000000..1b66f30 --- /dev/null +++ b/test/test_uscan @@ -0,0 +1,548 @@ +#!/bin/bash + +# Copyright (C) 2013, Rafael Laboissiere <rafael@laboissiere.net> +# +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u + +TESTTYPE=base +test_dir=$(readlink -f "${0%/*}") +. "$test_dir/lib_test_uscan" + +SUFFIX="1" +if command -v dpkg-vendor >/dev/null; then + VENDER="$(dpkg-vendor --query Vendor 2>/dev/null|tr 'A-Z' 'a-z')" + case "$VENDER" in + debian) SUFFIX="1" ;; + *) SUFFIX="0${VENDER}1" ;; + esac +fi + +if test "${1:-}" = --installed; then + COMMAND="uscan --no-conf --compression=xz" + shift +else + top_srcdir=$(readlink -f "${0%/*}/..") + make -C "$top_srcdir/scripts" uscan mk-origtargz uupdate debchange + PATH="$top_srcdir/scripts:$PATH" + export PATH + PERL5LIB="$top_srcdir/lib" + export PERL5LIB + COMMAND="uscan --no-conf --compression=xz" +fi + +COMMANDDEHS="$COMMAND --dehs" + +# comment out for debug +#COMMAND="$COMMAND --debug" + +tearDown(){ + killHttpServer + echo +} + +trap tearDown EXIT + +containsName(){ + echo "$1" | grep -qF "$2" + echo $? +} + +validXML(){ + echo "$1" | perl -ne 's/<[^\/].*?>.*?<\/.*>//g;$open++ if/<[^\/].*?>/;$open-- if/<\/.*>/;if(!$open and /^\s+\w/){$false++}}{exit ($false || $open) ? 1 : 0' + echo $? +} + +. "$test_dir/shunit2-helper-functions.sh" + +# The following tests do the following: (1) create a minimal Debian package +# directory, containing minimal files debian/{changelog,watch,copyright}, +# (2) create a minimal repository, containing a tarball (built on the fly), +# (3) start an HTTP server that works offline, using the SimpleHTTPServer +# module of Python, and (4) run uscan inside that minimal universe. + + +# The following function tests the --repack feature +helperTestRepack() { + from_ext="$1" + to_comp="$2" + file_output="$3" + + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian/source + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=3 +http://localhost:$PORT/$PKG-(\d).$from_ext +END + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + echo -n '3.0 (quilt)' > "$TEMP_PKG_DIR"/$PKG/debian/source/format + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + if [ "$from_ext" = "tar.zstd" ] + then + ( cd "$TEMP_PKG_DIR"/repo ; + tar --zstd -cf $PKG-1.$from_ext $PKG/* ) + else + ( cd "$TEMP_PKG_DIR"/repo ; + tar -caf $PKG-1.$from_ext $PKG/* ) + fi + + OUTPUT=$( cd "$TEMP_PKG_DIR"/$PKG ; $COMMANDDEHS --repack --compression=$to_comp ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + + TARBALL=${PKG}_1.orig.tar.$to_comp + if [ "$from_ext" != "tar.$to_comp" ] + then + assertFalse 'unrepacked tarball still present' "[ -f "$TEMP_PKG_DIR"/${PKG}_1.orig.$from_ext ]" + fi + assertTrue 'pristine tarball is not created' "[ -f "$TEMP_PKG_DIR"/$TARBALL ]" + assertNotNull "pristine tarball is not $to_comp-compressed" \ + "$( file -L "$TEMP_PKG_DIR"/$TARBALL | grep "$file_output" )" + CONTENTS="$(tar atf "$TEMP_PKG_DIR"/$TARBALL)" + assertTrue 'file contents missing' \ + $(containsName "$CONTENTS" content) + assertTrue "malfored target in dehs output: $OUTPUT" $(validXML "$OUTPUT") + assertTrue "malfored target in dehs output: $OUTPUT" \ + $(containsName "$OUTPUT" "<target>$TARBALL</target>") + +} + +testRepackGZ_XZ() { helperTestRepack "tar.gz" "xz" "XZ compressed data" ; } +testRepackGZ_BZ2() { helperTestRepack "tar.gz" "bz2" "bzip2 compressed data" ; } +testRepackBZ2_GZ() { helperTestRepack "tar.bz2" "gz" "gzip compressed data" ; } +testRepackGZ_GZ() { helperTestRepack "tar.gz" "gz" "gzip compressed data" ; } +testRepackXZ_XZ() { helperTestRepack "tar.xz" "xz" "XZ compressed data" ; } +testRepackTGZ_XZ() { helperTestRepack "tgz" "xz" "XZ compressed data" ; } +testRepackTGZ_XZ() { helperTestRepack "tgz" "xz" "XZ compressed data" ; } +testRepackLZ_XZ() { helperTestRepack "tar.lzma" "xz" "XZ compressed data" ; } +testRepackZST_XZ() { helperTestRepack "tar.zst" "xz" "XZ compressed data" ; } +testRepackZSTD_XZ() { helperTestRepack "tar.zstd" "xz" "XZ compressed data" ; } + +# The following function tests the --repack feature, with a zip file +testRepackZip_XZ() { + to_comp=xz + file_output="XZ compressed data" + + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian/source + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=3 +http://localhost:$PORT/$PKG-(\d).zip +END + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + echo -n '3.0 (quilt)' > "$TEMP_PKG_DIR"/$PKG/debian/source/format + + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + ( cd "$TEMP_PKG_DIR"/repo ; + zip -q -r $PKG-1.zip * ) + + OUTPUT=$( (cd "$TEMP_PKG_DIR"/$PKG ; $COMMANDDEHS --repack --compression=$to_comp) ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + + TARBALL=${PKG}_1.orig.tar.$to_comp + assertTrue 'unrepacked zipfile present' "[ -f "$TEMP_PKG_DIR"/${PKG}-1.zip ]" + assertTrue 'pristine tarball is not created' "[ -f "$TEMP_PKG_DIR"/$TARBALL ]" + assertNotNull "pristine tarball is not $to_comp-compressed" \ + "$( file -L "$TEMP_PKG_DIR"/$TARBALL | grep "$file_output" )" + CONTENTS="$(tar atf "$TEMP_PKG_DIR"/$TARBALL)" + assertTrue 'file contents missing' \ + $(containsName "$CONTENTS" content) + assertTrue "malfored target in dehs output: $OUTPUT" $(validXML "$OUTPUT") + assertTrue "malfored target in dehs output: $OUTPUT" \ + $(containsName "$OUTPUT" "<target>$TARBALL</target>") + +} + + + +# The following function tests the Files-Excluded feature of uscan, which +# allows the selective exclusion of files from the upstream tarball before +# repacking it. + +helperCreateRepo () { + mkdir -p $PKG/debian + + cat <<END > $PKG/debian/watch +version=3 +${OPTS:-}http://localhost:$PORT/$PKG-(\d).tar.gz debian ${SCRIPT:-} +END + + cat <<END > $PKG/debian/changelog +$PKG (0+dfsg1-$SUFFIX) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + cat <<'END' > $PKG/debian/copyright +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Files-Excluded: exclude-this + exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +END + if [ -n "${SRCFORMAT:-}" ]; then + mkdir -p $PKG/debian/source + echo "$SRCFORMAT" > $PKG/debian/source/format + fi + + mkdir -p repo + touch repo/include-this + touch repo/exclude-this + touch repo/.hidden + mkdir -p "repo/; echo baz; #/" + mkdir -p repo/exclude-dir + touch repo/exclude-dir/file + mkdir -p repo/exclude-dir/subdir + touch repo/exclude-dir/subdir/file2 + mkdir -p repo/docs/html/js/ + touch repo/docs/html/js/jquery.js + +} + +helperTestContent() { + assertTrue 'file that must be present is excluded in the tarball' \ + $(containsName "$CONTENTS" include-this) + assertFalse 'file that must be excluded is present in the tarball' \ + $(containsName "$CONTENTS" exclude-this) + assertFalse "dir that must be excluded is present in the tarball" \ + $(containsName "$CONTENTS" exclude-dir) + assertFalse "subdir that must be excluded is present in the tarball" \ + $(containsName "$CONTENTS" subdir) + assertFalse "non-root-file that must be excluded is present in the tarball" \ + $(containsName "$CONTENTS" jquery.js) + assertFalse "hidden file that must be excluded is present in the zip file" \ + $(containsName "$CONTENTS" .hidden) + assertFalse "path with whitespace that must be excluded is present" \ + $(containsName "$CONTENTS" "; echo baz; #/") +} + +testFileExclusion() { + + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + ( + cd "$TEMP_PKG_DIR" + OPTS="opts=repacksuffix=+dfsg1,dversionmangle=s/@DEB_EXT@// " + SCRIPT="uupdate" + SRCFORMAT="3.0 (quilt)" + helperCreateRepo + cd repo + tar cfz $PKG-1.tar.gz * .hidden ) + + (cd "$TEMP_PKG_DIR"/$PKG ; $COMMAND) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + + TARBALL=${PKG}_1+dfsg1.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f "$TEMP_PKG_DIR"/${PKG}-1.tar.gz ]" + assertTrue 'pristine tarball is not created' "[ -f "$TEMP_PKG_DIR"/$TARBALL ]" + assertFalse 'pristine tarball is a symlink (nothing repacked?)' "[ -L "$TEMP_PKG_DIR"/$TARBALL ]" + assertNotNull 'pristine tarball is not XZ-compressed' \ + "$( file "$TEMP_PKG_DIR"/$TARBALL | grep -i 'XZ compressed data' )" + CONTENTS="$(tar atf "$TEMP_PKG_DIR"/$TARBALL)" + + helperTestContent + + # check uupdate + assertTrue 'pristine tarball is not extracted' "[ -f "$TEMP_PKG_DIR"/${PKG}-1+dfsg1/debian/changelog ]" + DVERSION=`dpkg-parsechangelog -l"$TEMP_PKG_DIR"/${PKG}-1+dfsg1/debian/changelog -SVersion` + assertEquals "uscan: Version should be 1+dfsg1-$SUFFIX but $DVERSION" "$DVERSION" "1+dfsg1-$SUFFIX" + +} + +# the same, but run from a separate directory (no way for uupdate, just download) +testFileExclusionSeparateDir() { + + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + ( + cd "$TEMP_PKG_DIR" + SCRIPT="" + OPTS="opts=repacksuffix=+dfsg1,dversionmangle=auto " + helperCreateRepo + cd repo + tar cfz $PKG-1.tar.gz * .hidden ) + + mkdir "$TEMP_PKG_DIR"/otherdir + ( + cd "$TEMP_PKG_DIR"/otherdir; + $COMMAND --package $PKG --force-download --upstream-version 1 \ + --watchfile ../$PKG/debian/watch --copyright-file ../$PKG/debian/copyright + ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + + TARBALL=${PKG}_1+dfsg1.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f "$TEMP_PKG_DIR"/${PKG}-1.tar.gz ]" + assertTrue 'pristine tarball is not created' "[ -f "$TEMP_PKG_DIR"/$TARBALL ]" + assertFalse 'pristine tarball is a symlink (nothing repacked?)' "[ -L "$TEMP_PKG_DIR"/$TARBALL ]" + assertNotNull 'pristine tarball is not XZ-compressed' \ + "$( file "$TEMP_PKG_DIR"/$TARBALL | grep -i 'XZ compressed data' )" + CONTENTS="$(tar atf "$TEMP_PKG_DIR"/$TARBALL)" + + helperTestContent + +} + +# The same, for a zip file that is being repacked + +testFileExclusionZipToTar() { + + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + ( + cd "$TEMP_PKG_DIR" + SRCFORMAT="3.0 (quilt)" + helperCreateRepo + cat <<END > $PKG/debian/watch +version=3 +opts=repacksuffix=+dfsg1,dversionmangle=s/@DEB_EXT@// http://localhost:$PORT/$PKG-(\d).zip debian uupdate +END + + cd repo + zip -q -r $PKG-1.zip * .hidden ) + + (cd "$TEMP_PKG_DIR"/$PKG ; $COMMAND --repack) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + + TARBALL=${PKG}_1+dfsg1.orig.tar.xz + assertTrue 'unrepacked zipfile not present' "[ -f "$TEMP_PKG_DIR"/${PKG}-1.zip ]" + assertTrue 'pristine tarball is not created' "[ -f "$TEMP_PKG_DIR"/$TARBALL ]" + assertNotNull 'pristine tarball is not xz-compressed' \ + "$( file "$TEMP_PKG_DIR"/$TARBALL | grep 'XZ compressed data' )" + CONTENTS="$(tar atf "$TEMP_PKG_DIR"/$TARBALL)" + helperTestContent + + # check uupdate + assertTrue 'pristine tarball is not extracted' "[ -f "$TEMP_PKG_DIR"/${PKG}-1+dfsg1/debian/changelog ]" + DVERSION=`dpkg-parsechangelog -l"$TEMP_PKG_DIR"/${PKG}-1+dfsg1/debian/changelog -SVersion` + assertEquals "uscan: Version should be 1+dfsg1-$SUFFIX but $DVERSION" "$DVERSION" "1+dfsg1-$SUFFIX" + +} + +testPlainMode() { + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=4 +opts="searchmode=plain" \ +http://localhost:$PORT/src.json http://localhost:$PORT/foo-(\d).zip +END + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + ( cd "$TEMP_PKG_DIR"/repo ; + zip -q -r $PKG-1.zip *; + cat > src.json <<END +{"1.0":{"tarball":"http://localhost:$PORT/foo-1.zip"}} +END + ) + + OUTPUT=$( (cd "$TEMP_PKG_DIR"/$PKG ; $COMMANDDEHS) ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + + TARBALL=${PKG}_1.orig.tar.$to_comp + assertTrue 'unrepacked zipfile present' "[ -f "$TEMP_PKG_DIR"/${PKG}-1.zip ]" + +} + +testLinksWithRelativeBase() { + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + to_comp=xz + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=4 +http://localhost:$PORT/foo/index.html foo-([\d\.]+).zip +END + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + for href in foo-1.zip /foo/foo-1.zip //localhost:$PORT/foo/foo-1.zip ../foo/foo-1.zip x/../../foo/foo-1.zip; do + ( cd "$TEMP_PKG_DIR"/repo/foo ; + zip -q -r $PKG-1.zip *; + zip -q -r $PKG-0.9.zip *; + cat > index.html <<END +<html><body> +<base href="/foo/" /> +<a href="$href">foo-1.zip</a> +</body></html> +END + ) + + (cd "$TEMP_PKG_DIR"/$PKG ; $COMMAND) + assertEquals "uscan: exit_code!=0 but exit_code=0 with $href" "$?" "0" + done + + assertTrue 'unrepacked zipfile present' "[ -f "$TEMP_PKG_DIR"/${PKG}-1.zip ]" + +} + +testComponentDehsOutput() { + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=4 +http://localhost:$PORT/$PKG-(\d).zip debian + +opts="searchmode=plain,component=baz" \ +http://localhost:$PORT/src.json http://localhost:$PORT/foo-(\d).zip +END + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + ( cd "$TEMP_PKG_DIR"/repo ; + zip -q -r $PKG-1.zip *; + cat > src.json <<END +{"1.0":{"tarball":"http://localhost:$PORT/foo-1.zip"}} +END + ) + + OUTPUT=$( (cd "$TEMP_PKG_DIR"/$PKG ; $COMMANDDEHS --report --dehs) ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + assertTrue "malfored target in dehs output: $OUTPUT" $(validXML "$OUTPUT") + assertTrue "malfored target in dehs output: $OUTPUT" \ + $(containsName "$OUTPUT" '<component id="baz">') + assertTrue "malfored target in dehs output: $OUTPUT" \ + $(containsName "$OUTPUT" "<component-upstream-version>1</component-upstream-version>") +} + +testSimpleHeader() { + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian/source + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=4 +http://localhost:$PORT/$PKG-(\d).zip debian + +opts="searchmode=plain,component=baz,filenamemangle=s/.*-(@ANY_VERSION@@ARCHIVE_EXT@)/baz-\$1/" \ +http://localhost:$PORT/src.json http://localhost:$PORT/foo-(\d).zip +END + + echo -n '3.0 (quilt)' > "$TEMP_PKG_DIR"/$PKG/debian/source/format + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + ( cd "$TEMP_PKG_DIR"/repo ; + zip -q -r $PKG-1.zip *; + cat > src.json <<END +{"1.0":{"tarball":"http://localhost:$PORT/foo-1.zip"}} +END + ) + + OUTPUT=$( (cd "$TEMP_PKG_DIR"/$PKG ; $COMMAND -v \ + --http-header http://localhost:$PORT@Simple-Token=localtoken \ + --http-header http://another.com@Ext-Token=exttoken \ + ) ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + assertTrue "per-host header not exported: $OUTPUT" \ + $(containsName "$OUTPUT" "Set per-host custom header Simple-Token for http://localhost:$PORT/foo") + assertFalse "ext per-host header is exported: $OUTPUT" \ + $(containsName "$OUTPUT" "Set per-host custom header Ext-Token") +} + +. shunit2 diff --git a/test/test_uscan_ftp b/test/test_uscan_ftp new file mode 100755 index 0000000..d35db8c --- /dev/null +++ b/test/test_uscan_ftp @@ -0,0 +1,489 @@ +#!/bin/bash +# vim: set shiftwidth=4 tabstop=8 noexpandtab: + +# Copyright (C) 2018, Osamu Aoki <osamu@debian.org> +# +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u + +TESTTYPE=FTP +. ./lib_test_uscan + +DEB_HOST_OS="$(dpkg-architecture -qDEB_HOST_ARCH_OS)" +if [ "$DEB_HOST_OS" = "kfreebsd" ]; then + # kbsd has a non-working semaphore, that is needed here. + echo "This test is not supported on $(dpkg-architecture -qDEB_HOST_ARCH), skipping" + exit 0 +fi + +COMMAND="uscan --no-conf" + +# set safe defaults +WEBSCRIPT=":" +DEBUGECHO=":" +DEBUGLSLR=":" +DEBUGBASH=":" +# comment out for debug +#COMMAND="$COMMAND --debug" +#COMMAND="$COMMAND --verbose" +#DEBUGECHO=echo +#DEBUGLSLR="ls -laR" +#DEBUGLSLR="ls -la" +#DEBUGBASH="bash -i" + +# Initial Debian revision value is distribution dependent +SUFFIX="1" +if command -v dpkg-vendor >/dev/null; then + VENDER="$(dpkg-vendor --query Vendor 2>/dev/null|tr 'A-Z' 'a-z')" + case "$VENDER" in + debian) SUFFIX="1" ;; + *) SUFFIX="0${VENDER}1" ;; + esac +fi + +cleanup(){ + kill -9 $(cat $TMPDIR/$REPOPATH/pid) + rm -rf $TMPDIR + echo "" +} + +spawnFtpServer(){ + ( + local USCAN_FTP_SERVER=${USCAN_FTP_SERVER:-ftpserver.py} + mkdir -p "$TMPDIR/$REPOPATH" + cd "$TMPDIR/$REPOPATH" || exit 1 + echo "FTP starting ... $TMPDIR/$REPOPATH" + local pid + python3 "$test_dir/uscan/$USCAN_FTP_SERVER" 2>log & + pid=$! + echo $pid > pid + while ! [ -s port ]; do + sleep 2s + if ! kill -0 $pid 2> /dev/null ; then + echo "The FTP server returned an error:" + cat log + exit 1 + fi + done + ) +} + +trap cleanup 1 2 3 13 15 + +containsName(){ + echo "$1" | grep -qF "$2" + echo $? +} + +. "${0%/*}/shunit2-helper-functions.sh" + +# The following tests do the following: (1) create a minimal Debian package +# directory, containing minimal files debian/{changelog,watch,copyright}, +# (2) create a minimal repository, containing a tarball (built on the fly), +# (3) start an FTP server that works offline, using the pyftpdlib +# module of Python, and (4) run uscan inside that minimal universe. + +# make debian/ in `pwd` +# debian/watch contains $WATCHVER and $WATCHLINE with template URL updated +makeDebianDir() { + DEBNAME=${1:-foo} # Debian source package name + DEBVER=${2:-1.0} # Debian source package version + mkdir -p debian/source + + cat <<END > debian/rules +%: + dh $@ +END +chmod 755 debian/rules + + cat <<END > debian/changelog +$DEBNAME ($DEBVER) unstable; urgency=low + + * Release of the $DEBNAME package $DEBVER. + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + # debian/source/format + case $DEBVER in + *-*) # non-native package + echo "3.0 (quilt)" > debian/source/format + ;; + *) # native package + echo "3.0 (native)" > debian/source/format + ;; + esac + # debian/copyright + echo "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/" \ + > debian/copyright + # debian/watch + echo "version=$WATCHVER" > debian/watch + echo "$WATCHLINE" | sed -e "s,@@@url@@@,ftp://127.0.0.1:${PORT}/,g" - \ + >> debian/watch + # debian/upstream/signing-key.asc + mkdir -p debian/upstream + cp -f $test_dir/uscan/PUBLIC_KEY.asc debian/upstream/signing-key.asc +} + + +# make tarball in $REPOPATH/$POOLPATH +makeUpstreamTar() { + UPNAME=${1:-foo} # Upstream package name + UPVER=${2:-1.0} # upstream package version + COMPRESSION=${3:-gz} # archve compression type + TYPE=${4:-non-native} # set this if native-type upstream + OLDDIR=`pwd` + mkdir -p $TMPDIR/$REPOPATH/$POOLPATH/$UPNAME-$UPVER + cd $TMPDIR/$REPOPATH/$POOLPATH + touch $UPNAME-$UPVER/FILE.$UPNAME.$UPVER + if [ "$TYPE" = "native" ]; then + cd $TMPDIR/$REPOPATH/$POOLPATH/$UPNAME-$UPVER + makeDebianDir $UPNAME $UPVER + cd $TMPDIR/$REPOPATH/$POOLPATH + fi + case $COMPRESSION in + gz|gzip) + NEWTAR=$UPNAME-$UPVER.tar + tar -cf $NEWTAR $UPNAME-$UPVER + NEWTAR=$UPNAME-$UPVER.tar.gz + tar -czf $NEWTAR $UPNAME-$UPVER + ;; + bz2|bzip2) + NEWTAR=$UPNAME-$UPVER.tar + tar -cf $NEWTAR $UPNAME-$UPVER + NEWTAR=$UPNAME-$UPVER.tar.bz2 + tar --bzip2 -cf $NEWTAR $UPNAME-$UPVER + ;; + xz) + NEWTAR=$UPNAME-$UPVER.tar + tar -cf $NEWTAR $UPNAME-$UPVER + NEWTAR= $UPNAME-$UPVER.tar.xz + tar --xz -cf $NEWTAR $UPNAME-$UPVER + ;; + zip) + NEWTAR=$UPNAME-$UPVER.zip + zip -r $NEWTAR $UPNAME-$UPVER + ;; + *) echo "Wrong compression mode: $COMPRESSION" + exit 1 + ;; + esac + # make $NEWTAR.asc + $GPG --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --secret-keyring $PRIVATE_KEYRING --default-key 72543FAF \ + --armor --detach-sign $NEWTAR + if [ "$COMPRESSION" != "zip" ]; then + NEWTAR=$UPNAME-$UPVER.tar + $GPG --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --secret-keyring $PRIVATE_KEYRING --default-key 72543FAF \ + --armor --detach-sign $NEWTAR + + fi + cd $OLDDIR +} + +# setup a common watch file test environment +helperWatch() { + local SITESCRIPT=${1:-siteWebNonNative} + local VEROLD=${2:-1.0} + local VERNEW=${3:-2.0} + local PREFIX="${4:-}" + local TMPDIR=$(mktemp -d) + ORIGDIR=`pwd` + PKG=${PKG:-foo} + REPOPATH=${REPOPATH:-repo} + POOLPATH=${POOLPATH:-pool} + GZREPACK=${GZREPACK:-gz} + XCOMMAND=${XCOMMAND:-$COMMAND} + WATCHVER="${WATCHVER:-3}" + WATCHLINE0="@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate" + WATCHLINE="${WATCHLINE:-$WATCHLINE0}" + cd $TMPDIR + # start FTP server with its root at $TMPDIR/$REPOPATH + spawnFtpServer || exit 1 + PORT=$(cat $TMPDIR/$REPOPATH/port) + $DEBUGECHO " ***** ftp://localhost:$PORT started showing $TMPDIR/$REPOPATH *****" + # make web site + $SITESCRIPT + # make local $VEROLD source tree + tar -xzf $TMPDIR/$REPOPATH/$POOLPATH/${PKG}-${VEROLD}.tar.gz + if [ -n "${PREFIX}" ]; then + mv $TMPDIR/${PKG}-${VEROLD} $TMPDIR/${PKG}-${PREFIX}${VEROLD} + fi + mv $TMPDIR/${PKG}-${PREFIX}${VEROLD} $TMPDIR/${PKG} + cd $TMPDIR/${PKG} + if [ ! -d debian ]; then + makeDebianDir $PKG ${PREFIX}${VEROLD}-$SUFFIX + fi + local UUPDATE="" + if grep -q "uupdate" $TMPDIR/${PKG}/debian/watch ; then + UUPDATE=uupdate + fi + local PGP="" + if grep -q "pgpurlmangle" $TMPDIR/${PKG}/debian/watch ; then + PGP=pgp + fi + if grep -q "pgpmode *= *auto" $TMPDIR/${PKG}/debian/watch ; then + PGP=pgp + fi + if grep -q "pgpmode *= *previous" $TMPDIR/${PKG}/debian/watch ; then + PGP=pgp + fi + $XCOMMAND + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + cd $TMPDIR + $DEBUGLSLR + UTARBALL=${PKG}-${VERNEW}.tar.gz + STARBALL=${PKG}_${PREFIX}${VERNEW}.orig.tar.$GZREPACK + assertTrue "$UTARBALL missing: $WATCHLINE" "[ -f $UTARBALL ]" + assertTrue "$STARBALL missing: $WATCHLINE" "[ -f $STARBALL ]" + if [ "$PGP" = "pgp" ]; then + UTARSIG=${PKG}-${VERNEW}.tar.gz.asc + if [ ! -f $UTARSIG ]; then + UTARSIG=${PKG}-${VERNEW}.tar.asc + fi + STARSUG=${PKG}_${PREFIX}${VERNEW}.orig.tar.$GZREPACK.asc + assertTrue "$UTARSIG and *.sig missing: $WATCHLINE" "[ -f $UTARSIG ]" + assertTrue "$STARSIG missing: $WATCHLINE" "[ -f $STARSIG ]" + fi + # check uupdate + if [ "$UUPDATE" = "uupdate" ]; then + cd $TMPDIR/${PKG}-${PREFIX}${VERNEW} + assertTrue 'pristine tarball is not extracted' "[ -f debian/changelog ]" + DVERSION=`dpkg-parsechangelog -ldebian/changelog -SVersion` + assertEquals "uscan: Version should be ${PREFIX}${VERNEW}-$SUFFIX but $DVERSION" "$DVERSION" "${PREFIX}${VERNEW}-$SUFFIX" + cd $TMPDIR + fi + $DEBUGBASH + cd $ORIGDIR + cleanup + unset REPOPATH + unset POOLPATH + unset GZREPACK + unset XCOMMAND + unset WATCHVER + unset WATCHLINE +} + +# setup a common watch file test environment with Zip upstream +helperWatchZip() { + local SITESCRIPT=${1:-siteWebNonNative} + local VEROLD=${2:-1.0} + local VERNEW=${3:-2.0} + local PREFIX="${4:-}" + local TMPDIR=$(mktemp -d) + ORIGDIR=`pwd` + PKG=${PKG:-foo} + REPOPATH=${REPOPATH:-repo} + POOLPATH=${POOLPATH:-pool} + GZREPACK=${GZREPACK:-xz} + XCOMMAND=${XCOMMAND:-$COMMAND} + WATCHVER="${WATCHVER:-3}" + WATCHLINE0="@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate" + WATCHLINE="${WATCHLINE:-$WATCHLINE0}" + cd $TMPDIR + # start FTP server with its root at $TMPDIR/$REPOPATH + spawnFtpServer || exit 1 + PORT=$(cat $TMPDIR/$REPOPATH/port) + $DEBUGECHO " ***** ftp://localhost:$PORT started showing $TMPDIR/$REPOPATH *****" + # make web site + $SITESCRIPT + # make local $VEROLD source tree + unzip $TMPDIR/$REPOPATH/$POOLPATH/${PKG}-${VEROLD}.zip + if [ -n "$PREFIX" ]; then + mv $TMPDIR/${PKG}-${VEROLD} $TMPDIR/${PKG}-${PREFIX}${VEROLD} + fi + mv $TMPDIR/${PKG}-${PREFIX}${VEROLD} $TMPDIR/${PKG} + cd $TMPDIR/${PKG} + if [ ! -d debian ]; then + makeDebianDir $PKG ${PREFIX}${VEROLD}-$SUFFIX + fi + local UUPDATE="" + if grep -q "uupdate" $TMPDIR/${PKG}/debian/watch ; then + UUPDATE=uupdate + fi + local PGP="" + if grep -q "pgpurlmangle" $TMPDIR/${PKG}/debian/watch ; then + PGP=pgp + fi + if grep -q "pgpmode *= *auto" $TMPDIR/${PKG}/debian/watch ; then + PGP=pgp + fi + if grep -q "pgpmode *= *previous" $TMPDIR/${PKG}/debian/watch ; then + PGP=pgp + fi + $XCOMMAND + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + cd $TMPDIR + $DEBUGLSLR + UTARBALL=${PKG}-${VERNEW}.zip + STARBALL=${PKG}_${PREFIX}${VERNEW}.orig.tar.$GZREPACK + assertTrue "$UTARBALL missing: $WATCHLINE" "[ -f $UTARBALL ]" + assertTrue "$STARBALL missing: $WATCHLINE" "[ -f $STARBALL ]" + if [ "$PGP" = "pgp" ]; then + UTARSIG=${PKG}-${VERNEW}.zip.asc + STARSUG=${PKG}_${PREFIX}${VERNEW}.orig.tar.$GZREPACK.asc + assertTrue "$UTARSIG and *.sig missing: $WATCHLINE" "[ -f $UTARSIG ]" + assertTrue "$STARSIG missing: $WATCHLINE" "[ -f $STARSIG ]" + fi + # check uupdate + if [ "$UUPDATE" = "uupdate" ]; then + cd $TMPDIR/${PKG}-${PREFIX}${VERNEW} + assertTrue 'pristine tarball is not extracted' "[ -f debian/changelog ]" + DVERSION=`dpkg-parsechangelog -ldebian/changelog -SVersion` + assertEquals "uscan: Version should be ${PREFIX}${VERNEW}-$SUFFIX but $DVERSION" "$DVERSION" "${PREFIX}${VERNEW}-$SUFFIX" + cd $TMPDIR + fi + $DEBUGBASH + cd $ORIGDIR + cleanup + unset REPOPATH + unset POOLPATH + unset GZREPACK + unset XCOMMAND + unset WATCHVER + unset WATCHLINE +} + +siteNonNative() { + local PKG=${1:-foo} + local EXTRA=${2:-} + makeUpstreamTar $PKG 0.0 gz non-native + makeUpstreamTar $PKG 1.0 gz non-native + makeUpstreamTar $PKG 2.0 gz non-native + mkdir -p $TMPDIR/$REPOPATH/0.0/$PKG/ooo/ + mkdir -p $TMPDIR/$REPOPATH/1.0/$PKG/ooo/ + mkdir -p $TMPDIR/$REPOPATH/2.0/$PKG/ooo/ + if [ -n "$EXTRA" ]; then + makeUpstreamTar $PKG 3.0 gz non-native + mkdir -p $TMPDIR/$REPOPATH/3.0/$PKG/ooo/ + fi + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz.asc $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.asc $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.asc + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz.asc $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.asc $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.asc + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz.asc $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.asc $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.asc + if [ -n "$EXTRA" ]; then + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz.asc $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.asc $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.asc + fi +} + +siteNonNativeZip() { + local PKG=${1:-foo} + local EXTRA=${2:-} + makeUpstreamTar $PKG 0.0 zip non-native + makeUpstreamTar $PKG 1.0 zip non-native + makeUpstreamTar $PKG 2.0 zip non-native + mkdir -p $TMPDIR/$REPOPATH/0.0/$PKG/ooo/ + mkdir -p $TMPDIR/$REPOPATH/1.0/$PKG/ooo/ + mkdir -p $TMPDIR/$REPOPATH/2.0/$PKG/ooo/ + if [ -n "$EXTRA" ]; then + makeUpstreamTar $PKG 3.0 gz non-native + mkdir -p $TMPDIR/$REPOPATH/3.0/$PKG/ooo/ + fi + ln -sf ../../../$POOLPATH/${PKG}-0.0.zip $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.zip + ln -sf ../../../$POOLPATH/${PKG}-0.0.zip.asc $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.zip.asc + ln -sf ../../../$POOLPATH/${PKG}-1.0.zip $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.zip + ln -sf ../../../$POOLPATH/${PKG}-1.0.zip.asc $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.zip.asc + ln -sf ../../../$POOLPATH/${PKG}-2.0.zip $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.zip + ln -sf ../../../$POOLPATH/${PKG}-2.0.zip.asc $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.zip.asc + if [ -n "$EXTRA" ]; then + ln -sf ../../../$POOLPATH/${PKG}-3.0.zip $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.zip + ln -sf ../../../$POOLPATH/${PKG}-3.0.zip.asc $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.zip.asc + fi +} + +siteNonNativeR() { + local PKG=${1:-foo} + local EXTRA=${2:-} + makeUpstreamTar $PKG 0.0 gz non-native + makeUpstreamTar $PKG 1.0 gz non-native + makeUpstreamTar $PKG 2.0 gz non-native + mkdir -p $TMPDIR/$REPOPATH/0.0/$PKG/ooo/ + mkdir -p $TMPDIR/$REPOPATH/1.0/$PKG/ooo/ + mkdir -p $TMPDIR/$REPOPATH/2.0/$PKG/ooo/ + if [ -n "$EXTRA" ]; then + makeUpstreamTar $PKG 3.0 gz non-native + mkdir -p $TMPDIR/$REPOPATH/3.0/$PKG/ooo/ + fi + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-0.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz.asc $TMPDIR/$REPOPATH/3.0/$PKG/ooo/${PKG}-0.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-1.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz.asc $TMPDIR/$REPOPATH/2.0/$PKG/ooo/${PKG}-1.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-2.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz.asc $TMPDIR/$REPOPATH/1.0/$PKG/ooo/${PKG}-2.0.tar.gz.asc + if [ -n "$EXTRA" ]; then + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-3.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz.asc $TMPDIR/$REPOPATH/0.0/$PKG/ooo/${PKG}-3.0.tar.gz.asc + fi +} + +# test a watch files + +### VERSION 4 ### +# standard tests + +# test non-native package with uupdate, bare FTP server in normal order +testWatch4NonNative() { + WATCHVER=4 + WATCHLINE='opts=pgpsigurlmangle=s/$/.asc/ @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative +} + +# test --download-current-version, bare FTP server in normal order +testWatch4NonNativeDlCurrent() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-current-version" + WATCHLINE='opts=pgpsigurlmangle=s/$/.asc/ @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative 1.0 1.0 +} + +# test --download-version, bare FTP server in normal order +testWatch4NonNativeDlUversion() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-version 0.0" + WATCHLINE='opts=pgpsigurlmangle=s/$/.asc/ @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative 1.0 0.0 +} + +# test non-native package with uupdate, bare FTP server in normal order with upstream ZIP +testWatch4NonNativeZip() { + WATCHVER=4 + COMPRESSION='zip' + WATCHLINE='opts=pgpsigurlmangle=s/$/.asc/ @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatchZip siteNonNativeZip +} + +# test non-native package with uupdate, bare FTP server in normal order with repack to xz +testWatch4NonNativeXz() { + WATCHVER=4 + GZREPACK='xz' + WATCHLINE='opts=pgpsigurlmangle=s/$/.asc/,compression=xz,repack @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative +} + +# test non-native package with uupdate, bare FTP server in normal order with ungzsig +testWatch4NonNativeUngzsig() { + WATCHVER=4 + WATCHLINE='opts=pgpsigurlmangle=s/.gz$/.asc/,decompress @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative +} + +. shunit2 diff --git a/test/test_uscan_git b/test/test_uscan_git new file mode 100755 index 0000000..61b5c81 --- /dev/null +++ b/test/test_uscan_git @@ -0,0 +1,207 @@ +#!/bin/bash + +# Copyright (C) 2018, Xavier <yadd@debian.org> +# +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u +#set -x + +TESTTYPE=Git +. ./lib_test_uscan + +COMMAND="chronic_sh uscan --no-conf --compression=xz --dehs" + +# prevent the local from messing with this test +export GIT_CONFIG_NOGLOBAL=1 +export HOME="" +export XDG_CONFIG_HOME="" + +# comment out for debug +#COMMAND="$COMMAND --verbose" +#COMMAND="$COMMAND --debug" + +cleanup(){ + rm -rf "$TEMP_PKG_DIR" +} + +spawnGitRepo(){ + mkdir -p "$TEMP_PKG_DIR/repo" + (cd "$TEMP_PKG_DIR/repo" || exit 1 + chronic_sh git init + git config user.name "Joe Developer" + git config user.email "none@debian.org" + touch changelog file.c extra.c + echo 'extra.c export-ignore' >.gitattributes + chronic_sh git add changelog file.c extra.c .gitattributes + chronic_sh git commit -a -m 'Init' + for version in 1.0 2.0; do + echo "# Version $version" >> file.c + cat >> changelog <<END +Version $version + +END + chronic_sh git commit -a -m "Releasing $version" + chronic_sh git tag -s -u 72543FAF -m "Version $version" "v$version" + done) +} + +trap cleanup EXIT + +containsName(){ + echo "$1" | grep -F -q "$2" + echo $? +} + +# shellcheck source=shunit2-helper-functions.sh +. "${0%/*}/shunit2-helper-functions.sh" + +PKG=foo + +makeDebianDir() { + WATCHARGS=$1 + TEMP_PKG_DIR=$(mktemp -d --tmpdir="$SHUNIT_TMPDIR" uscan_git.XXXXXX) + if [ -z "$TEMP_PKG_DIR" ]; then + echo "Failed to create temporary directory" >&2 + exit 1 + fi + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian/upstream + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian/source + spawnGitRepo + + cat <<END > "$TEMP_PKG_DIR/$PKG/debian/watch" +version=4 +opts="mode=git,gitmode=shallow,$WATCHARGS" \ +file:///$TEMP_PKG_DIR/repo refs/tags/v([\\d\\.]+) debian +END + + cat <<END > "$TEMP_PKG_DIR/$PKG/debian/changelog" +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + echo '3.0 (quilt)' > "$TEMP_PKG_DIR/$PKG/debian/source/format" + cp -f "$test_dir/uscan/PUBLIC_KEY.asc" "$TEMP_PKG_DIR/$PKG/debian/upstream/signing-key.asc" +} + +makeDebianDirWithUpstream() { + WATCHARGS=$1 + makeDebianDir "$WATCHARGS" + cd "$TEMP_PKG_DIR/$PKG" || exit 1 + chronic_sh git init + chronic_sh git remote add upstream "file:///$TEMP_PKG_DIR/repo" + chronic_sh git fetch upstream + cd - > /dev/null || exit 1 +} + +makeDebianDirHead() { + WATCHARGS=$1 + makeDebianDir "$WATCHARGS" + cat <<END > "$TEMP_PKG_DIR/$PKG/debian/watch" +version=4 +opts="mode=git,pretty=0.0+git%cd.%h" \ +file:///$TEMP_PKG_DIR/repo HEAD +END +} + +helperLaunch() { + WATCHARGS=$1 + ARG="${2:-}" + CMD_ARG="${3:-}" + if test "$ARG" = "upstream"; then + makeDebianDirWithUpstream "$WATCHARGS" + elif test "$ARG" = "HEAD"; then + makeDebianDirHead "$WATCHARGS" + else + makeDebianDir "$WATCHARGS" + fi + ( cd "$TEMP_PKG_DIR/$PKG" || exit 1 ; $COMMAND $CMD_ARG --watchfile=debian/watch ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" +} + +testGit() { + helperLaunch "pgpmode=none" + TARBALL=${PKG}_2.0.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$TEMP_PKG_DIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$TEMP_PKG_DIR/$TARBALL' ]" + cleanup +} + +testGitHead() { + helperLaunch "pgpmode=none" HEAD + ORIG=$(find "$TEMP_PKG_DIR" | perl -ne 'print if/\/foo.*\.orig\.tar\.xz$/') + UPSTREAM=$(find "$TEMP_PKG_DIR" | perl -ne 'print if/\/foo.*(?<!orig)\.tar\.xz$/') + assertTrue 'downloaded tarfile not present' "[ -f '$UPSTREAM' ]" + assertTrue 'pristine tarball is not created' "[ -f '$ORIG' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$ORIG' ]" + cleanup +} + +testGitSignedTag() { + helperLaunch "pgpmode=gittag" + TARBALL=${PKG}_2.0.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$TEMP_PKG_DIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$TEMP_PKG_DIR/$TARBALL' ]" + cleanup +} + +testGitUpstream() { + helperLaunch "pgpmode=none" upstream + TARBALL=${PKG}_2.0.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$TEMP_PKG_DIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$TEMP_PKG_DIR/$TARBALL' ]" + cleanup +} + +testGitUpstreamSignedTag() { + helperLaunch "pgpmode=gittag" upstream + TARBALL=${PKG}_2.0.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$TEMP_PKG_DIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$TEMP_PKG_DIR/$TARBALL' ]" + cleanup +} + +testGitIgnoreExclusions() { + helperLaunch "gitexport=all" + assertTrue 'downloaded tarfile is incomplete' \ + "tar tf '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' '${PKG}-2.0/extra.c'" + cleanup +} + +testGitUpstreamIgnoreExclusions() { + helperLaunch "gitexport=all" upstream + assertTrue 'downloaded tarfile is incomplete' \ + "tar tf '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' '${PKG}-2.0/extra.c'" + cleanup +} + +testGitSignedTagWithDestDir() { + DESTDIR=$TEMP_PKG_DIR/destdir + mkdir -p $DESTDIR + helperLaunch "pgpmode=gittag" "" "--destdir $TEMP_PKG_DIR/destdir" + TARBALL=${PKG}_2.0.orig.tar.xz + assertTrue 'downloaded tarfile not present' "[ -f '$DESTDIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$DESTDIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$DESTDIR/$TARBALL' ]" + cleanup +} + +# shellcheck disable=SC1091 +. shunit2 diff --git a/test/test_uscan_group b/test/test_uscan_group new file mode 100755 index 0000000..c5e7ef9 --- /dev/null +++ b/test/test_uscan_group @@ -0,0 +1,210 @@ +#!/bin/bash + +# Copyright (C) 2020, Xavier Guimard <yadd@debian.org> +# +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u + +TESTTYPE=base +test_dir=$(readlink -f "${0%/*}") +. "$test_dir/lib_test_uscan" + +SUFFIX="1" +if command -v dpkg-vendor >/dev/null; then + VENDER="$(dpkg-vendor --query Vendor 2>/dev/null|tr 'A-Z' 'a-z')" + case "$VENDER" in + debian) SUFFIX="1" ;; + *) SUFFIX="0${VENDER}1" ;; + esac +fi + +if test "${1:-}" = --installed; then + COMMAND="uscan --no-conf --compression=gz" + shift +else + top_srcdir=$(readlink -f "${0%/*}/..") + make -C "$top_srcdir/scripts" uscan mk-origtargz uupdate debchange + PATH="$top_srcdir/scripts:$PATH" + export PATH + PERL5LIB="$top_srcdir/lib" + export PERL5LIB + COMMAND="uscan --no-conf --compression=xz" +fi + +COMMANDDEHS="$COMMAND --dehs" + +# comment out for debug +#COMMAND="$COMMAND --debug" + +tearDown(){ + killHttpServer + echo +} + +trap tearDown EXIT + +containsName(){ + echo "$1" | grep -qF "$2" + echo $? +} + +makeRepo() { + lv="$1" + cmpopt1="$2" + lv1="$3" + cmpopt2="$4" + lv2="$5" + cmpopt3="$6" + lv3="$7" + cmpopt4="$8" + lv4="$9" + prev="${10}" + PKG=foo + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR") + + mkdir -p "$TEMP_PKG_DIR"/$PKG/debian/source + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/repo/port) + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/watch +version=4 +http://localhost:$PORT/ .*$PKG-([\d\.]+).tar.gz $lv + +opts="dversionmangle=auto,component=bar1$cmpopt1" http://localhost:$PORT/ .*bar1-([\d\.]+).tar.gz $lv1 +opts="dversionmangle=auto,component=bar2$cmpopt2" http://localhost:$PORT/ .*bar2-([\d\.]+).tar.gz $lv2 +opts="dversionmangle=auto,component=bar3$cmpopt3" http://localhost:$PORT/ .*bar3-([\d\.]+).tar.gz $lv3 +opts="dversionmangle=auto,component=bar4$cmpopt4" http://localhost:$PORT/ .*bar4-([\d\.]+).tar.gz $lv4 +END + + cat <<END > "$TEMP_PKG_DIR"/$PKG/debian/changelog +$PKG ($prev) unstable; urgency=medium + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + + echo -n '3.0 (quilt)' > "$TEMP_PKG_DIR"/$PKG/debian/source/format + mkdir -p "$TEMP_PKG_DIR"/repo/foo + touch "$TEMP_PKG_DIR"/repo/foo/content + + # Upstream repo + ( cd "$TEMP_PKG_DIR"/repo ; + tar -czf $PKG-1.0.0.tar.gz $PKG/* ) + + for i in 1 2 3 4; do + # Upstream repo + mkdir -p "$TEMP_PKG_DIR"/repo/bar$i + touch "$TEMP_PKG_DIR"/repo/bar$i/content + ( cd "$TEMP_PKG_DIR"/repo ; + tar -czf bar$i-2.0.$i.tar.gz bar$i/* ) + # Debian dir + mkdir $TEMP_PKG_DIR/$PKG/bar$i + echo '{"name":"bar'$i'","version":"'1.0.$i'"}' > $TEMP_PKG_DIR/$PKG/bar$i/package.json + done +} + +helperDownload() { + next="${11}" + makeRepo "$@" + + OUTPUT=$( cd "$TEMP_PKG_DIR"/$PKG ; $COMMANDDEHS --dehs ) + BASETARBALL=${PKG}_$next.orig + assertTrue 'pristine tarball foo is not created' "[ -f "$TEMP_PKG_DIR"/$BASETARBALL.tar.gz ]" + assertTrue "malformed target in dehs output: $OUTPUT" \ + $(containsName "$OUTPUT" "<target>$BASETARBALL.tar.gz</target>") + for i in 1 2 3 4; do + assertTrue "pristine tarball bar$i is not created" "[ -f "$TEMP_PKG_DIR"/$BASETARBALL-bar$i.tar.gz ]" + assertTrue "malformed target in dehs output: $OUTPUT" \ + $(containsName "$OUTPUT" "<component-target>$BASETARBALL-bar$i.tar.gz</component-target>") + done + #cat "$TEMP_PKG_DIR"/$PKG/debian/watch +} + +testCmpIgnore() { + helperDownload "debian" "" "ignore" "" "ignore" "" "ignore" "" "ignore" "0.0.1" "1.0.0" +} + +testCmpGroup() { + helperDownload "group" "" "group" "" "group" "" "group" "" "group" "0.0.1+~1" "1.0.0+~2.0.1+~2.0.2+~2.0.3+~2.0.4" +} + +testCmpGroupOneCmpChanged() { + helperDownload "group" "" "group" "" "group" "" "group" "" "group" "1.0.0+~2.0.1+~2.0.2+~2.0.2+~2.0.4" "1.0.0+~2.0.1+~2.0.2+~2.0.3+~2.0.4" +} + +testCmpPartialGroup() { + helperDownload "group" "" "group" "" "group" "" "ignore" "" "ignore" "0.0.1+~1" "1.0.0+~2.0.1+~2.0.2" +} + +testCmpPartialGroup2() { + helperDownload "group" "" "group" "" "ignore" "" "group" "" "ignore" "0.0.1+~1" "1.0.0+~2.0.1+~2.0.3" +} + +testCmpChecksum() { + helperDownload "group" "" "checksum" "" "checksum" "" "checksum" "" "checksum" "0.0.1+~1" "1.0.0+~cs8.0.10" +} + +testCmpChecksumOneCmpChanged() { + helperDownload "group" "" "checksum" "" "checksum" "" "checksum" "" "checksum" "1.0.0+~cs8.0.9" "1.0.0+~cs8.0.10" +} + +testCmpGroupAndChecksum() { + helperDownload "group" "" "group" "" "checksum" "" "checksum" "" "checksum" "0.0.1+~1" "1.0.0+~2.0.1+~cs6.0.9" +} + +testCmpGroupIgnoreAndChecksum() { + helperDownload "group" "" "group" "" "ignore" "" "checksum" "" "checksum" "0.0.1+~1" "1.0.0+~2.0.1+~cs4.0.7" +} + +helperNoDownload() { + next="${10}" + makeRepo "$@" + + OUTPUT=$( cd "$TEMP_PKG_DIR"/$PKG ; $COMMANDDEHS --dehs 2>&1 ) + assertTrue "bad change detected: $OUTPUT" \ + $(containsName "$OUTPUT" "<status>up to date</status>") + BASETARBALL=${PKG}_$next.orig + assertTrue 'pristine tarball foo is created' "[ ! -f "$TEMP_PKG_DIR"/$BASETARBALL.tar.gz ]" +} + +testCmpIgnoreND() { + helperNoDownload "debian" "" "ignore" "" "ignore" "" "ignore" "" "ignore" "1.0.0" +} + +testCmpGroupND() { + helperNoDownload "group" "" "group" "" "group" "" "group" "" "group" "1.0.0+~2.0.1+~2.0.2+~2.0.3+~2.0.4" +} + +testCmpGroupRepackND() { + helperNoDownload "group" "" "group" "" "group" "" "group" "" "group" "1.0.0+~2.0.1~ds+~2.0.2+~2.0.3+~2.0.4" +} + +testCmpChecksumND() { + helperNoDownload "group" "" "checksum" "" "checksum" "" "checksum" "" "checksum" "1.0.0+~cs8.0.10" +} + +# Same test but here Ctype detects change even if previous checksum is wrong +testCmpChecksumCtype() { + helperDownload "group" ",ctype=nodejs" "checksum" ",ctype=nodejs" "checksum" ",ctype=nodejs" "checksum" ",ctype=nodejs" "checksum" "1.0.0+~cs8.0.10" "1.0.0+~cs8.0.10" +} + +testCmpIgnoreCtype() { + helperNoDownload "debian" ",ctype=nodejs" "ignore" "" "ignore" "" "ignore" "" "ignore" "1.0.0" + assertTrue "Component change is not detected: $OUTPUT" \ + $(containsName "$OUTPUT" "Newest version of bar1 on remote site is 2.0.1, local version is 1.0.1") +} + +. shunit2 diff --git a/test/test_uscan_mangle b/test/test_uscan_mangle new file mode 100755 index 0000000..409e16e --- /dev/null +++ b/test/test_uscan_mangle @@ -0,0 +1,1543 @@ +#!/bin/bash + +# Copyright (C) 2013, Rafael Laboissiere <rafael@laboissiere.net> +# +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u + +TESTTYPE=Mangle +. ./lib_test_uscan + +COMMAND="uscan --no-conf" + +# set safe defaults +WEBSCRIPT=":" +DEBUGECHO=":" +DEBUGLSLR=":" +DEBUGBASH=":" +# comment out for debug +#COMMAND="$COMMAND --debug" +#COMMAND="$COMMAND --verbose" +#DEBUGECHO=echo +#DEBUGLSLR="ls -laR" +#DEBUGLSLR="ls -la" +#DEBUGBASH="bash -i" + +# Initial Debian revision value is distribution dependent +SUFFIX="1" +if command -v dpkg-vendor >/dev/null; then + VENDER="$(dpkg-vendor --query Vendor 2>/dev/null|tr 'A-Z' 'a-z')" + case "$VENDER" in + debian) SUFFIX="1" ;; + *) SUFFIX="0${VENDER}1" ;; + esac +fi + +tearDown(){ + killHttpServer + echo +} + +trap tearDown EXIT + +containsName(){ + echo "$1" | grep -qF "$2" + echo $? +} + +. "${0%/*}/shunit2-helper-functions.sh" + +# The following tests do the following: (1) create a minimal Debian package +# directory, containing minimal files debian/{changelog,watch,copyright}, +# (2) create a minimal repository, containing a tarball (built on the fly), +# (3) start an HTTP server that works offline, using the SimpleHTTPServer +# module of Python, and (4) run uscan inside that minimal universe. + +# make debian/ in `pwd` +# debian/watch contains $WATCHVER and $WATCHLINE with template URL updated +makeDebianDir() { + DEBNAME=${1:-foo} # Debian source package name + DEBVER=${2:-1.0} # Debian source package version + mkdir -p debian/source + + cat <<END > debian/rules +%: + dh $@ +END +chmod 755 debian/rules + + cat <<END > debian/changelog +$DEBNAME ($DEBVER) unstable; urgency=low + + * Release of the $DEBNAME package $DEBVER. + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + # debian/source/format + case $DEBVER in + *-*) # non-native package + echo "3.0 (quilt)" > debian/source/format + ;; + *) # native package + echo "3.0 (native)" > debian/source/format + ;; + esac + # debian/copyright + echo "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/" \ + > debian/copyright + if [ "${FILEEXCLUDE:-0}" = "1" ]; then + # exclude just for main + cat <<'END' >> debian/copyright +Files-Excluded: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +END + elif [ "${FILEEXCLUDE:-0}" = "2" ]; then + # exclude for main(=foo) bar baz + cat <<'END' >> debian/copyright +Files-Excluded: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +Files-Excluded-bar: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +Files-Excluded-baz: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +END + elif [ "${FILEEXCLUDE:-0}" = "3" ]; then + # exclude for foo bar baz + cat <<'END' >> debian/copyright +Files-Excluded-foo: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +Files-Excluded-bar: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +Files-Excluded-baz: exclude-this + */exclude-dir + .* + */js/jquery.js + ;?echo?baz;?# +END + fi + # debian/watch + echo "version=$WATCHVER" > debian/watch + echo "$WATCHLINE" | sed -e "s,@@@url@@@,http://localhost:${PORT}/,g" - \ + >> debian/watch + # debian/upstream/signing-key.asc + mkdir -p debian/upstream + if [ "$KEYMODE" = "ASC" ]; then + cp -f $test_dir/uscan/PUBLIC_KEY.asc debian/upstream/signing-key.asc + else + cp -f "$GPGHOME/pubring.gpg" debian/upstream/signing-key.pgp + fi +} + + +# make tarball in $REPOPATH/$POOLPATH +makeUpstreamTar() { + UPNAME=${1:-foo} # Upstream package name + UPVER=${2:-1.0} # upstream package version + COMPRESSION=${3:-gz} # archve compression type + TYPE=${4:-non-native} # set this if native-type upstream + OLDDIR=`pwd` + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/$POOLPATH/$UPNAME-$UPVER + cd "$TEMP_PKG_DIR"/$REPOPATH/$POOLPATH + touch $UPNAME-$UPVER/FILE.$UPNAME.$UPVER + touch $UPNAME-$UPVER/include-this + touch $UPNAME-$UPVER/exclude-this + touch $UPNAME-$UPVER/.hidden + mkdir -p "$UPNAME-$UPVER/; echo baz; #/" + mkdir -p $UPNAME-$UPVER/exclude-dir + touch $UPNAME-$UPVER/exclude-dir/file + mkdir -p $UPNAME-$UPVER/subdir/exclude-dir + touch $UPNAME-$UPVER/subdir/exclude-dir/file2 + mkdir -p $UPNAME-$UPVER/docs/html/js/ + touch $UPNAME-$UPVER/docs/html/js/jquery.js + if [ "$TYPE" = "native" ]; then + cd "$TEMP_PKG_DIR"/$REPOPATH/$POOLPATH/$UPNAME-$UPVER + makeDebianDir $UPNAME $UPVER + cd "$TEMP_PKG_DIR"/$REPOPATH/$POOLPATH + fi + case $COMPRESSION in + gz|gzip) + NEWTAR=$UPNAME-$UPVER.tar.gz + tar -czf $NEWTAR $UPNAME-$UPVER + ;; + bz2|bzip2) + NEWTAR=$UPNAME-$UPVER.tar.bz2 + tar --bzip2 -cf $NEWTAR $UPNAME-$UPVER + ;; + xz) + NEWTAR= $UPNAME-$UPVER.tar.xz + tar --xz -cf $NEWTAR $UPNAME-$UPVER + ;; + zip) + NEWTAR=$UPNAME-$UPVER.zip + zip -r $NEWTAR $UPNAME-$UPVER + ;; + *) echo "Wrong compression mode: $COMPRESSION" + exit 1 + ;; + esac + case "${SIGMODE:-}" in # undefined SIGMODE → no sig + ASC) # make $NEWTAR.asc + $GPG --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --secret-keyring $PRIVATE_KEYRING --default-key 72543FAF \ + --armor --detach-sign $NEWTAR + ;; + BIN) #make $NEWTAR.sig + $GPG --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --secret-keyring $PRIVATE_KEYRING --default-key 72543FAF \ + --detach-sign $NEWTAR + ;; + SELF) #make $NEWTAR.gpg + $GPG --homedir "$GPGHOME" --no-options -q --batch --no-default-keyring \ + --secret-keyring $PRIVATE_KEYRING --default-key 72543FAF \ + --sign $NEWTAR + esac + + cd $OLDDIR +} + +# setup a common watch file test environment +helperWatch() { + local SITESCRIPT=${1:-siteWebNonNative} + local VEROLD=${2:-1.0} + local VERNEW=${3:-2.0} + local PREFIX="${4:-}" + TEMP_PKG_DIR=${TEMP_PKG_DIR:-$(mktemp -d -p "$SHUNIT_TMPDIR" uscan_mangle.XXXXXX)} + ORIGDIR=`pwd` + PKG=${PKG:-foo} + REPOPATH=${REPOPATH:-repo} + POOLPATH=${POOLPATH:-pool} + MGZREPACK=${MGZREPACK:-gz} + XCOMMAND=${XCOMMAND:-$COMMAND} + WATCHVER="${WATCHVER:-3}" + WATCHLINE0="@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate" + WATCHLINE="${WATCHLINE:-$WATCHLINE0}" + COMPONENTS=${COMPONENTS:-} + FILEEXCLUDE=${FILEEXCLUDE:-0} # no exclude + FILENAMEMANGLE=${FILENAMEMANGLE:-} + SIGMODE=${SIGMODE:-ASC} # ASC=ASCII or BIN=BINARY or SELF + KEYMODE=${KEYMODE:-ASC} # ASC=ASCII AEMORED or BIN=DEARMORED BINARY + cd "$TEMP_PKG_DIR" + # start HTTP server with its root at "$TEMP_PKG_DIR"/$REPOPATH + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/$REPOPATH/port) + $DEBUGECHO " ***** http://localhost:$PORT started showing "$TEMP_PKG_DIR"/$REPOPATH *****" + # make web site + $SITESCRIPT + # make local $VEROLD source tree + tar -xzf "$TEMP_PKG_DIR"/$REPOPATH/$POOLPATH/${PKG}-${VEROLD}.tar.gz + if [ -n "$PREFIX" ]; then + mv "$TEMP_PKG_DIR"/${PKG}-${VEROLD} "$TEMP_PKG_DIR"/${PKG}-${PREFIX}${VEROLD} + fi + mv "$TEMP_PKG_DIR"/${PKG}-${PREFIX}${VEROLD} "$TEMP_PKG_DIR"/${PKG} + cd "$TEMP_PKG_DIR"/${PKG} + if [ ! -d debian ]; then + makeDebianDir $PKG ${PREFIX}${VEROLD}-$SUFFIX + fi + local UUPDATE="" + if grep -q "uupdate" "$TEMP_PKG_DIR"/${PKG}/debian/watch ; then + UUPDATE=uupdate + fi + local PGP="" + if grep -q "pgpurlmangle" "$TEMP_PKG_DIR"/${PKG}/debian/watch ; then + PGP=pgp + fi + if grep -q "pgpmode *= *auto" "$TEMP_PKG_DIR"/${PKG}/debian/watch ; then + PGP=pgp + fi + if grep -q "pgpmode *= *previous" "$TEMP_PKG_DIR"/${PKG}/debian/watch ; then + PGP=pgp + fi + $XCOMMAND + assertEquals "uscan: exit_code!=0 but exit_code=0" "$?" "0" + cd "$TEMP_PKG_DIR" + $DEBUGLSLR + UTARBALL=${PKG}-${UVERSION:-${VERNEW}}.tar.gz + if [[ "$FILENAMEMANGLE" != *"$PKG"* ]]; then + UTARBALL=${PKG}-${UVERSION:-${VERNEW}}.tar.gz + else + UTARBALL=${PKG}-${UVERSION:-${VERNEW}}-filenamemangle.tar.gz + fi + STARBALL=${PKG}_${PREFIX}${VERNEW}.orig.tar.$MGZREPACK + if [ ! -f $STARBALL ]; then + # testWatch4WebNonNativeMUT0() only repacks its component tarballs. It does + # not repack the main upstream tarball, which is the usual behaviour when + # excluding files from the upstream source. This means we need to find the + # upstream tarball. + STARBALL=${PKG}_${PREFIX}${VERNEW}.orig.tar.gz + fi + assertTrue "$UTARBALL missing: $WATCHLINE" "[ -f $UTARBALL ]" + assertTrue "$STARBALL missing: $WATCHLINE" "[ -f $STARBALL ]" + if [ "$PGP" = "pgp" ]; then + UTARSIG=${PKG}-${UVERSION:-${VERNEW}}.tar.gz.sig + if [ ! -f $UTARSIG ]; then + UTARSIG=${PKG}-${UVERSION:-${VERNEW}}.tar.gz.asc + fi + STARSIG=${PKG}_${PREFIX}${VERNEW}.orig.tar.$MGZREPACK.asc + assertTrue "$UTARSIG and *.sig missing: $WATCHLINE" "[ -f $UTARSIG ]" + assertTrue "$STARSIG missing: $WATCHLINE" "[ -f $STARSIG ]" + fi + for cpnt in $COMPONENTS; do + if [[ "$FILENAMEMANGLE" != *"$cpnt"* ]]; then + UTARBALL=${cpnt}-${CMPVERSION:-${VERNEW}}.tar.gz + else + UTARBALL=${PKG}-${cpnt}-${CMPVERSION:-${VERNEW}}.tar.gz + fi + STARBALL=${PKG}_${PREFIX}${VERNEW}.orig-${cpnt}.tar.$MGZREPACK + assertTrue "$UTARBALL missing: $WATCHLINE" "[ -f $UTARBALL ]" + assertTrue "$STARBALL missing: $WATCHLINE" "[ -f $STARBALL ]" + if [ "$PGP" = "pgp" ]; then + UTARSIG=${cpnt}-${CMPVERSION:-${VERNEW}}.tar.gz.sig + if [ ! -f $UTARSIG ]; then + UTARSIG=${cpnt}-${CMPVERSION:-${VERNEW}}.tar.gz.asc + fi + STARSIG=${PKG}_${PREFIX}${VERNEW}.orig-${cpnt}.tar.$MGZREPACK.asc + assertTrue "$UTARSIG and *.sig missing: $WATCHLINE" "[ -f $UTARSIG ]" + # Skipping this: signature link skipped when upstream file is repacked + #assertTrue "$STARSIG missing: $WATCHLINE" "[ -f $STARSIG ]" + fi + done + # check uupdate + if [ "$UUPDATE" = "uupdate" ]; then + cd "$TEMP_PKG_DIR"/${PKG}-${PREFIX}${VERNEW} + assertTrue 'pristine tarball is not extracted' "[ -f debian/changelog ]" + DVERSION=`dpkg-parsechangelog -ldebian/changelog -SVersion` + assertEquals "uscan: Version should be ${PREFIX}${VERNEW}-$SUFFIX but $DVERSION" "$DVERSION" "${PREFIX}${VERNEW}-$SUFFIX" + if [ "$FILEEXCLUDE" != "3" ]; then + # main is dummy + assertTrue 'file that must be present is excluded in the tarball' '[ -f include-this ]' + fi + if [ "$FILEEXCLUDE" = "1" ] || [ "$FILEEXCLUDE" = "2" ]; then + assertFalse "file that must be excluded is present in the tarball" '[ -f exclude-this ]' + assertFalse "hidden file that must be excluded is present in the tarball" '[ -f .hidden ]' + assertFalse "dir that must be excluded is present in the tarball" '[ -d exclude-dir ]' + assertFalse "subdir that must be excluded is present in the tarball" '[ -d subdir/exclude-dir ]' + CONTENTS=$(ls -R) + assertFalse "non-root-file that must be excluded is present in the tarball" \ + $(containsName "$CONTENTS" jquery.js) + assertFalse "path with whitespace that must be excluded is present in the tarball" \ + $(containsName "$CONTENTS" "; echo baz; #/") + fi + for c in $COMPONENTS ; do + cd "$TEMP_PKG_DIR"/${PKG}-${PREFIX}${VERNEW}/$c + assertTrue 'file that must be present is excluded in the tarball' '[ -f include-this ]' + if [ "$FILEEXCLUDE" = "1" ] || [ "$FILEEXCLUDE" = "2" ]; then + assertFalse "file that must be excluded is present in the orig-$c.tar" '[ -f exclude-this ]' + assertFalse "hidden file that must be excluded is present in the orig-$c.tar" '[ -f .hidden ]' + assertFalse "dir that must be excluded is present in the orig-$c.tar" '[ -d exclude-dir ]' + assertFalse "subdir that must be excluded is present in the orig-$c.tar" '[ -d subdir/exclude-dir ]' + CONTENTS=$(ls -R) + assertFalse "non-root-file that must be excluded is present in the orig-$c.tar" \ + $(containsName "$CONTENTS" jquery.js) + assertFalse "path with whitespace that must be excluded is present in the orig-$c.tar" \ + $(containsName "$CONTENTS" "; echo baz; #/") + fi + done + cd "$TEMP_PKG_DIR" + fi + $DEBUGBASH + cd $ORIGDIR + unset REPOPATH + unset POOLPATH + unset MGZREPACK + unset XCOMMAND + unset WATCHVER + unset WATCHLINE + unset COMPONENTS + unset FILEEXCLUDE + unset FILENAMEMANGLE + unset SIGMODE + unset KEYMODE +} + +# setup a common watch file test environment to see user-agent +helperWatchUA() { + local SITESCRIPT=${1:-siteWebNonNative} + TEMP_PKG_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR" uscan_mangle.XXXXXX) + ORIGDIR=`pwd` + PKG=${PKG:-foo} + REPOPATH=${REPOPATH:-repo} + POOLPATH=${POOLPATH:-pool} + XCOMMAND=${XCOMMAND:-$COMMAND} + WATCHVER="${WATCHVER:-3}" + WATCHLINE0="@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate" + WATCHLINE="${WATCHLINE:-$WATCHLINE0}" + KEYMODE=${KEYMODE:-ASC} # ASC=ASCII AEMORED or BIN=DEARMORED BINARY + cd "$TEMP_PKG_DIR" + # start HTTP server with its root at "$TEMP_PKG_DIR"/$REPOPATH + spawnHttpServer + PORT=$(cat "$TEMP_PKG_DIR"/$REPOPATH/port) + $DEBUGECHO " ***** http://localhost:$PORT started showing "$TEMP_PKG_DIR"/$REPOPATH *****" + # make web site + $SITESCRIPT + # make local $VEROLD source tree + mkdir -p "$TEMP_PKG_DIR"/${PKG} + cd "$TEMP_PKG_DIR"/${PKG} + if [ ! -d debian ]; then + makeDebianDir $PKG 1.0-$SUFFIX + fi + $XCOMMAND + USERAGENTX="$(grep -ie '^User-Agent:' ../repo/log |head -1 | perl -p -e "s/\r//g" )" + assertTrue "Bad $USERAGENTX" "[ \"$USERAGENTX\" = \"User-Agent: $USERAGENT\" ]" + echo "SENT: \"User-Agent: $USERAGENT\"" + echo "GOT : \"$USERAGENTX\"" + $DEBUGBASH + cd $ORIGDIR + unset REPOPATH + unset POOLPATH + unset XCOMMAND + unset WATCHVER + unset WATCHLINE + unset KEYMODE +} + +# populate pool directory +siteNative() { + local PKG=${1:-foo} + makeUpstreamTar $PKG 0.0 gz native + makeUpstreamTar $PKG 1.0 gz native + makeUpstreamTar $PKG 2.0 gz native + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/ + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz +} + +siteNonNative() { + local PKG=${1:-foo} + local EXTRA=${2:-} + makeUpstreamTar $PKG 0.0 gz non-native + makeUpstreamTar $PKG 1.0 gz non-native + makeUpstreamTar $PKG 2.0 gz non-native + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/ + if [ -n "$EXTRA" ]; then + makeUpstreamTar $PKG 3.0 gz non-native + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/3.0/$PKG/ooo/ + fi + if [ "${SIGMODE:-}" = "ASC" ]; then + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz.asc + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz.asc + if [ -n "$EXTRA" ]; then + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz.asc + fi + elif [ "${SIGMODE:-}" = "BIN" ]; then + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz.sig + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz.sig + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz.sig + if [ -n "$EXTRA" ]; then + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz.sig + fi + elif [ "${SIGMODE:-}" = "SELF" ]; then + ln -sf ../../../$POOLPATH/${PKG}-0.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/0.0/$PKG/ooo/${PKG}-0.0.tar.gz.gpg + ln -sf ../../../$POOLPATH/${PKG}-1.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/1.0/$PKG/ooo/${PKG}-1.0.tar.gz.gpg + ln -sf ../../../$POOLPATH/${PKG}-2.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/2.0/$PKG/ooo/${PKG}-2.0.tar.gz.gpg + if [ -n "$EXTRA" ]; then + ln -sf ../../../$POOLPATH/${PKG}-3.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/3.0/$PKG/ooo/${PKG}-3.0.tar.gz.gpg + fi + fi +} + +# hide siteNative behind a web page +siteWebNative() { + siteNative + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/foo/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +</body> +<html> +END +} + +siteWebNonNative() { + siteNonNative + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/foo/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +</body> +<html> +END +} + +siteWebNonNativeRecWithBase() { + siteNonNative "$@" + for DIR in "$TEMP_PKG_DIR"/$REPOPATH/[0-9].*; do + [ -d "$DIR" ] && cat <<END > "$DIR"/index.html +<html> +<head> + <meta charset="utf-8"> +<base href="/${DIR##*/}/foo/ooo/x.html"/> +</head> +<body> +<a href="foo-${DIR##*/}.tar.gz">Blah</a> <br/ > +</body> +<html> +END + done +} + +siteWebNonNativeR() { + makeUpstreamTar foo 0.0 gz non-native + makeUpstreamTar foo 1.0 gz non-native + makeUpstreamTar foo 2.0 gz non-native + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/123/foo/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/124/foo/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/125/foo/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/325/foo/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/424/foo/ooo/ + mkdir -p "$TEMP_PKG_DIR"/$REPOPATH/523/foo/ooo/ + if [ "$SIGMODE" = "ASC" ]; then + ln -sf ../../../$POOLPATH/foo-0.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/125/foo/ooo/foo-0.0.tar.gz + ln -sf ../../../$POOLPATH/foo-1.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/124/foo/ooo/foo-1.0.tar.gz + ln -sf ../../../$POOLPATH/foo-2.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/123/foo/ooo/foo-2.0.tar.gz + ln -sf ../../../$POOLPATH/foo-0.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/325/foo/ooo/foo-0.0.tar.gz.asc + ln -sf ../../../$POOLPATH/foo-1.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/424/foo/ooo/foo-1.0.tar.gz.asc + ln -sf ../../../$POOLPATH/foo-2.0.tar.gz.asc "$TEMP_PKG_DIR"/$REPOPATH/523/foo/ooo/foo-2.0.tar.gz.asc + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/125/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/124/foo/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/123/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +<a href="/325/foo/ooo/foo-0.0.tar.gz.asc">Very old sig</a> <br/ > +<a href="/424/foo/ooo/foo-1.0.tar.gz.asc">A bit OLD sig</a> <br /> +<a href="/523/foo/ooo/foo-2.0.tar.gz.asc">Latest sig</a> <br /> +</body> +<html> +END + elif [ "$SIGMODE" = "BIN" ]; then + ln -sf ../../../$POOLPATH/foo-0.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/125/foo/ooo/foo-0.0.tar.gz + ln -sf ../../../$POOLPATH/foo-1.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/124/foo/ooo/foo-1.0.tar.gz + ln -sf ../../../$POOLPATH/foo-2.0.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/123/foo/ooo/foo-2.0.tar.gz + ln -sf ../../../$POOLPATH/foo-0.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/325/foo/ooo/foo-0.0.tar.gz.sig + ln -sf ../../../$POOLPATH/foo-1.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/424/foo/ooo/foo-1.0.tar.gz.sig + ln -sf ../../../$POOLPATH/foo-2.0.tar.gz.sig "$TEMP_PKG_DIR"/$REPOPATH/523/foo/ooo/foo-2.0.tar.gz.sig + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/125/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/124/foo/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/123/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +<a href="/325/foo/ooo/foo-0.0.tar.gz.sig">Very old sig</a> <br/ > +<a href="/424/foo/ooo/foo-1.0.tar.gz.sig">A bit OLD sig</a> <br /> +<a href="/523/foo/ooo/foo-2.0.tar.gz.sig">Latest sig</a> <br /> +</body> +<html> +END + elif [ "$SIGMODE" = "SELF" ]; then + ln -sf ../../../$POOLPATH/foo-0.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/325/foo/ooo/foo-0.0.tar.gz.gpg + ln -sf ../../../$POOLPATH/foo-1.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/424/foo/ooo/foo-1.0.tar.gz.gpg + ln -sf ../../../$POOLPATH/foo-2.0.tar.gz.gpg "$TEMP_PKG_DIR"/$REPOPATH/523/foo/ooo/foo-2.0.tar.gz.gpg + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/125/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/124/foo/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/123/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +<a href="/325/foo/ooo/foo-0.0.tar.gz.gpg">Very old sig</a> <br/ > +<a href="/424/foo/ooo/foo-1.0.tar.gz.gpg">A bit OLD sig</a> <br /> +<a href="/523/foo/ooo/foo-2.0.tar.gz.gpg">Latest sig</a> <br /> +</body> +<html> +END + fi +} + +sitePrWebNonNative() { + siteNonNative + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/boo/xxx/boo-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/boo/xxx/boo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/boo/xxx/boo-2.0.tar.gz">Latest</a> <br /> +</body> +<html> +END +} + +siteWebNonNativeLarge() { + makeUpstreamTar foo 19990101 gz non-native + makeUpstreamTar foo 20000101 gz non-native + makeUpstreamTar foo 20010101 gz non-native + mkdir -p $REPOPATH/0.0/foo/ooo/ + mkdir -p $REPOPATH/1.0/foo/ooo/ + mkdir -p $REPOPATH/2.0/foo/ooo/ + ln -sf ../../../$POOLPATH/foo-19990101.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/0.0/foo/ooo/foo-19990101.tar.gz + ln -sf ../../../$POOLPATH/foo-20000101.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/1.0/foo/ooo/foo-20000101.tar.gz + ln -sf ../../../$POOLPATH/foo-20010101.tar.gz "$TEMP_PKG_DIR"/$REPOPATH/2.0/foo/ooo/foo-20010101.tar.gz + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/foo/ooo/foo-19990101.tar.gz">Very old</a> <br/ > +<a href="/1.0/foo/ooo/foo-20000101.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/foo/ooo/foo-20010101.tar.gz">Latest</a> <br /> +</body> +<html> +END +} + +siteXmlNonNative() { + siteNonNative + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<Key>/0.0/foo/ooo/foo-0.0.tar.gz</Key> <br/ > +<Key>/1.0/foo/ooo/foo-1.0.tar.gz</Key> <br /> +<Key>/2.0/foo/ooo/foo-2.0.tar.gz</Key> <br /> +</body> +<html> +END +} + +siteWebNonNativeMUT() { + siteNonNative foo + siteNonNative bar EXTRA + siteNonNative baz EXTRA + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/foo/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz.asc">Latest sig</a> <br /> +<a href="/0.0/bar/ooo/bar-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/bar/ooo/bar-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/bar/ooo/bar-2.0.tar.gz">Latest</a> <br /> +<a href="/3.0/bar/ooo/bar-3.0.tar.gz">OOPS Latest</a> <br /> +<a href="/3.0/bar/ooo/bar-3.0.tar.gz.asc">Latest sig</a> <br /> +<a href="/0.0/baz/ooo/baz-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/baz/ooo/baz-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/baz/ooo/baz-2.0.tar.gz">Latest</a> <br /> +<a href="/3.0/baz/ooo/baz-3.0.tar.gz">OOPS Latest</a> <br /> +<a href="/3.0/baz/ooo/baz-3.0.tar.gz.asc">Latest sig</a> <br /> +</body> +<html> +END +} + +siteWebNonNativeMUT_filenamemangle() { + siteNonNative foo + siteNonNative bar EXTRA + siteNonNative baz EXTRA + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/foo/ooo/foo-1.0.tar.gz">A bit old</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz">Latest</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz.asc">Latest sig</a> <br /> +<a href="/0.0/bar/ooo/bar-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/bar/ooo/bar-1.0.tar.gz">A bit old</a> <br /> +<a href="/2.0/bar/ooo/bar-2.0.tar.gz">Latest</a> <br /> +<a href="/3.0/bar/ooo/bar-2.0.tar.gz.asc">Latest sig</a> <br /> +<a href="/0.0/baz/ooo/baz-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/baz/ooo/baz-1.0.tar.gz">A bit old</a> <br /> +<a href="/2.0/baz/ooo/baz-2.0.tar.gz">Latest</a> <br /> +<a href="/3.0/baz/ooo/baz-2.0.tar.gz.asc">Latest sig</a> <br /> +</body> +<html> +END +} + +siteWebNonNativeGetOnlyHref() { + siteNonNative foo + cat <<END > "$TEMP_PKG_DIR"/$REPOPATH/index.html +<html> +<head> + <meta charset="utf-8"> +</head> +<body> +<a href="/0.0/foo/ooo/foo-0.0.tar.gz">Very old</a> <br/ > +<a href="/1.0/bar/ooo/foo-1.0.tar.gz">A bit OLD</a> <br /> +<a href="/2.0/foo/ooo/foo-2.0.tar.gz" data-foobar-href="">Latest</a> <br /> +<aueu href="/2.0/foo/ooo/foo-3.0.tar.gz" data-foobar-href="">Nothing here</a> <br /> +</body> +<html> +END +} + +# test a watch files + +### VERSION3 ### +# version locking calls suffer changes due to uupdate calling differences + +# test --download-current-version +testWatch3WebNonNativeDlCurrent() { + WATCHVER=3 + XCOMMAND="$COMMAND --download-current-version" + WATCHLINE='@@@url@@@/ (?:.*)/foo-([\.\d]+).tar.gz debian uupdate' + helperWatch siteWebNonNative 1.0 1.0 +} + +# test --download-version +testWatch3WebNonNativeDlUversion() { + WATCHVER=3 + XCOMMAND="$COMMAND --download-version 0.0" + WATCHLINE='@@@url@@@/ (?:.*)/foo-([\.\d]+).tar.gz debian uupdate' + helperWatch siteWebNonNative 1.0 0.0 +} + +# test --download-debversion uupdate +testWatch3WebNonNativeDlDversion() { + WATCHVER=3 + XCOMMAND="$COMMAND --download-debversion 0.0-1" + WATCHLINE='@@@url@@@/ (?:.*)/foo-([\.\d]+).tar.gz debian uupdate' + helperWatch siteWebNonNative 1.0 0.0 +} + +### VERSION 4 ### +# standard tests + +# test native package w/o uupdate, bare HTTP server in normal order +testWatch4Native() { + WATCHVER=4 + WATCHLINE='@@@url@@@/([\.\d]+)/(.+)/(.+)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian' + helperWatch siteNative +} + +# test non-native package with uupdate, bare HTTP server in normal order +testWatch4NonNative() { + WATCHVER=4 + WATCHLINE='@@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative +} + +# test non-native package with uupdate, bare HTTP server with dirversionmangle +testWatch4NonNativeDMangle() { + WATCHVER=4 + WATCHLINE='opts="dirversionmangle=s/^\d*[13579]\./0~$&/, uversionmangle=s/^\d*[13579]\./0~$&/" @@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch "siteNonNative foo EXTRA" +} + +# ... and without dirversionmangle, should return version 3 +testWatch4NonNativeDMangleWithoutD() { + WATCHVER=4 + WATCHLINE='@@@url@@@([\.\d]+)/(.+)/(.+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch "siteNonNative foo EXTRA" 1.0 3.0 +} + +# test non-native package with uupdate, bare HTTP server with dirversionmangle and base +testWatch4NonNativeDMangleB() { + WATCHVER=4 + WATCHLINE='opts="dirversionmangle=s/^\d*[13579]\./0~$&/, uversionmangle=s/^\d*[13579]\./0~$&/" @@@url@@@([\.\d]+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch "siteWebNonNativeRecWithBase foo EXTRA" +} + +# ... and without dirversionmangle, should return version 3 +testWatch4NonNativeDMangleBWithoutD() { + WATCHVER=4 + WATCHLINE='@@@url@@@([\.\d]+)/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch "siteWebNonNativeRecWithBase foo EXTRA" 1.0 3.0 +} + +# test 3 parameter watch line +testWatch4WebNative() { + WATCHVER=4 + WATCHLINE='@@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian' + helperWatch siteWebNative +} + +# test normal web page +testWatch4WebNonNative() { + WATCHVER=4 + helperWatch +} + +# test normal web page (Files-exclude) +testWatch4WebNonNativeFE() { + MGZREPACK=xz + FILEEXCLUDE=1 + WATCHVER=4 + helperWatch +} + +# test normal web page (file path reverse order) +testWatch4WebNonNativeR() { + WATCHVER=4 + helperWatch siteWebNonNativeR +} + +# test for downloadurlmangle and filenamemangle for tricky web page +testWatch4PrWebNonNative() { + WATCHVER=4 + WATCHLINE='opts="downloadurlmangle = s%boo/xxx%@PACKAGE@/ooo% ; s%boo-%@PACKAGE@-%, \ + filenamemangle = s%.*boo-(.*)%@PACKAGE@-$1% " \ + @@@url@@@/ (?:.*)/boo@ANY_VERSION@@ARCHIVE_EXT@ \ + debian uupdate' + helperWatch sitePrWebNonNative +} + +# test --download-current-version +testWatch4NonNativeDlCurrent() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-current-version" + WATCHLINE='@@@url@@@/([\d\.]+)/@PACKAGE@/ooo/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative 1.0 1.0 +} + +# test --download-version +testWatch4NonNativeDlUversion() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-version 0.0" + WATCHLINE='@@@url@@@/([\d\.]+)/@PACKAGE@/ooo/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative 1.0 0.0 +} + +# test --download-debversion uupdate +testWatch4NonNativeDlDversion() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-debversion 0.0-1" + WATCHLINE='@@@url@@@/([\d\.]+)/@PACKAGE@/ooo/ @PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteNonNative 1.0 0.0 +} + +# test --download-current-version +testWatch4WebNonNativeDlCurrent() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-current-version" + WATCHLINE='@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteWebNonNative 1.0 1.0 +} + +# test --download-version +testWatch4WebNonNativeDlUversion() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-version 0.0" + WATCHLINE='@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteWebNonNative 1.0 0.0 +} + +# test --download-debversion uupdate +testWatch4WebNonNativeDlDversion() { + WATCHVER=4 + XCOMMAND="$COMMAND --download-debversion 0.0-1" + WATCHLINE='@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteWebNonNative 1.0 0.0 +} + +# Debian version is 0.19990101 for future proof while upstream is 19990101 +testWatch4WebNonNativeLarge() { + WATCHVER=4 + WATCHLINE='opts=" dversionmangle = s/0\.(.*)/$1/ , \ + oversionmangle = s/(.*)/0.$1/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteWebNonNativeLarge 20000101 20010101 0. +} + +# test for pagemangle +testWatch4XmlNonNative() { + WATCHVER=4 + WATCHLINE='opts="pagemangle = \ + s%<Key>([^<]*)</Key>%<Key><a href=\"$1\">$1</a></Key>%g" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteXmlNonNative +} + +# test user-agent string setting via opts= +testWatch4WebNonNativeUA() { + WATCHVER=4 + KEYMODE=BIN + USERAGENT="foo/bar; baz:12,3.45" + WATCHLINE='opts="useragent= '$USERAGENT' "'" \ +"'@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatchUA + unset USERAGENT +} + +# test repack and compression +testWatch4WebNonNativeBZ2() { + WATCHVER=4 + WATCHLINE='opts=repack,compression=bz2 @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + MGZREPACK=bz2 + helperWatch +} + +# test repack and compression +testWatch4WebNonNativeXZ() { + MGZREPACK=xz + WATCHVER=4 + WATCHLINE='opts=repack,compression=xz @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test spaces everywhere +testWatch4PrWebNonNativeXZ() { + MGZREPACK=xz + WATCHVER=4 + WATCHLINE='opts = "downloadurlmangle = s%boo/xxx%@PACKAGE@/ooo% ; s%boo-%@PACKAGE@-%, \ + filenamemangle = s%.*boo-(.*)%@PACKAGE@-$1% , \ + repack , compression=xz" \ + @@@url@@@/ (?:.*)/boo@ANY_VERSION@@ARCHIVE_EXT@ \ + debian uupdate' + helperWatch sitePrWebNonNative +} + +# test get strictly href from links and not something like foo-href. See #904578 and MR !25 +testWatchGetOnlyHref() { + WATCHVER=4 + WATCHLINE='@@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch siteWebNonNativeGetOnlyHref 1.0 2.0 +} + +### VERSION 4 with sig check ### + +# test normal web page with sig(asc) +testWatch4WebNonNativeSig() { + WATCHVER=4 + WATCHLINE='opts = "pgpsigurlmangle = s%(.*)%$1.asc%" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(asc) with < and > +testWatch4WebNonNativeSigAngleBraket() { + WATCHVER=4 + WATCHLINE='opts = "pgpsigurlmangle = s<(.*)><$1.asc>" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(asc) with < and > with space +testWatch4WebNonNativeSigAngleBraketSpace() { + WATCHVER=4 + WATCHLINE='opts = "pgpsigurlmangle = s<(.*)> <$1.asc>" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(asc) with < and > with tab +testWatch4WebNonNativeSigAngleBraketTab() { + WATCHVER=4 + WATCHLINE='opts = "pgpsigurlmangle = s<(.*)> <$1.asc>" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(asc) with [ and ] +testWatch4WebNonNativeSigSquareBraket() { + WATCHVER=4 + WATCHLINE='opts = "pgpsigurlmangle = s[(.*)][$1.asc]" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(asc) with { and } +testWatch4WebNonNativeSigCurlyBraket() { + WATCHVER=4 + WATCHLINE='opts = "pgpsigurlmangle = s{(.*)}{$1.asc}" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(asc) - auto +testWatch4WebNonNativeSigAuto() { + WATCHVER=4 + WATCHLINE='opts = "pgpmode = auto" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian uupdate' + helperWatch +} + +# test normal web page with sig(bin) (Files-exclude) +testWatch4WebNonNativeFESig() { + MGZREPACK=xz + FILEEXCLUDE=1 + WATCHVER=4 + SIGMODE=BIN + KEYMODE=BIN + WATCHLINE='opts = "pgpsigurlmangle = s%(.*)%$1.sig%" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ \ + debian uupdate' + helperWatch +} + +# test normal web page with sig (different file path for sig and tar; reverse order) +testWatch4WebNonNativeRSig() { + WATCHVER=4 + WATCHLINE='opts = "pgpmode=next" @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts = "pgpmode=previous" @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@.asc previous uupdate' + helperWatch siteWebNonNativeR +} + +# test normal web page with sig (different file path for sig and tar; reverse order, BIN) +testWatch4WebNonNativeRSigBIN() { + WATCHVER=4 + SIGMODE=BIN + WATCHLINE='opts = "pgpmode=next" @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts = "pgpmode=previous" @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@.sig previous uupdate' + helperWatch siteWebNonNativeR +} + +# test normal web page with sig (different file path for sig and tar; reverse order, BIN BIN) +testWatch4WebNonNativeRSigBINiBIN() { + WATCHVER=4 + SIGMODE=BIN + KEYMODE=BIN + WATCHLINE='opts = "pgpmode=next" @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts = "pgpmode=previous" @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@.sig previous uupdate' + helperWatch siteWebNonNativeR +} + +# test normal web page with sig (self) +testWatch4WebNonNativeSelfSig() { + WATCHVER=4 + SIGMODE=SELF + WATCHLINE='opts = "pgpmode = self" \ + @@@url@@@/ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@.gpg debian uupdate' + helperWatch siteWebNonNativeR +} + +### VERSION 4 only ### + +# filenamemangle supports two patterns, each causing different behaviour. +# * The first pattern replaces the existing URL with the new filename. +# * The second pattern modifies the filename component, creating a new (and invalid) URL. + +# test normal web page (filenamemangle on main upstream tarball [pattern 1]) +testWatch4WebNonNative_filenamemangle1a() { + WATCHVER=4 + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s#.+/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)#$1-filenamemangle$2#" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian' + helperWatch siteWebNonNative +} + +# test normal web page (signature and filenamemangle on main upstream tarball [pattern 1]) +testWatch4WebNonNative_filenamemangle1b() { + WATCHVER=4 + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s#.+/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)#$1-filenamemangle$2#, \ + pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian' + helperWatch siteWebNonNative +} + +# test normal web page (filenamemangle on main upstream tarball [pattern 2]) +testWatch4WebNonNative_filenamemangle1c() { + WATCHVER=4 + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s/(\d\S+)(@ARCHIVE_EXT@)/$1-filenamemangle$2/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian' + helperWatch siteWebNonNative +} + +# test normal web page (signature and filenamemangle on main upstream tarball [pattern 2]) +testWatch4WebNonNative_filenamemangle1d() { + WATCHVER=4 + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s/(\d\S+)(@ARCHIVE_EXT@)/$1-filenamemangle$2/, \ + pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian' + helperWatch siteWebNonNative +} + +# test normal web page (MUT) +testWatch4WebNonNativeMUT() { + MGZREPACK=xz + WATCHVER=4 + COMPONENTS="bar baz" + SIGMODE=BIN + FILEEXCLUDE=2 + WATCHLINE=' +opts=" pgpsigurlmangle=s/$/.sig/" @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar,pgpsigurlmangle=s/$/.sig/" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz,pgpsigurlmangle=s/$/.sig/" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same uupdate' + helperWatch siteWebNonNativeMUT +} + +# test normal web page (MUT, filenamemangle on main upstream tarball [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle1a() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s#.+/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)#$1-filenamemangle$2#" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signature and filenamemangle on main upstream tarball [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle1b() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s#.+/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)#$1-filenamemangle$2#, \ + pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on main upstream tarball [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle1c() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)/$1-filenamemangle$2/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signature and filenamemangle on main upstream tarball [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle1d() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=foo + WATCHLINE=' +opts="filenamemangle=s/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)/$1-filenamemangle$2/, \ + pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on first component tarball [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle2a() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=bar + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s#.+/(bar-)#@PACKAGE@-$1#" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signature and filenamemangle on first component tarball [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle2b() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=bar + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s#.+/(bar-)#@PACKAGE@-$1#, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on first component tarball [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle2c() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=bar + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s/(bar-)/@PACKAGE@-$1/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signature and filenamemangle on first component tarball [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle2d() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=bar + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s/(bar-)/@PACKAGE@-$1/, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on second component tarball [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle3a() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=baz + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s#.+/(baz-)#@PACKAGE@-$1#" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signature and filenamemangle on second component tarball [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle3b() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=baz + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s#.+/(baz-)#@PACKAGE@-$1#, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on second component tarball [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle3c() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=baz + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s/(baz-)/@PACKAGE@-$1/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signature and filenamemangle on second component tarball [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle3d() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE=baz + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s/(baz-)/@PACKAGE@-$1/, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on both component tarballs [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle4a() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="$COMPONENTS" + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s#.+/(bar-)#@PACKAGE@-$1#" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s#.+/(baz-)#@PACKAGE@-$1#" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signatures and filenamemangle on both component tarballs [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle4b() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="$COMPONENTS" + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s#.+/(bar-)#@PACKAGE@-$1#, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s#.+/(baz-)#@PACKAGE@-$1#, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on both component tarballs [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle4c() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="$COMPONENTS" + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s/(bar-)/@PACKAGE@-$1/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s/(baz-)/@PACKAGE@-$1/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signatures and filenamemangle on both component tarballs [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle4d() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="$COMPONENTS" + WATCHLINE=' + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s/(bar-)/@PACKAGE@-$1/, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s/(baz-)/@PACKAGE@-$1/, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on all upstream tarballs [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle5a() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="foo $COMPONENTS" + WATCHLINE=' +opts="filenamemangle=s#.+/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)#$1-filenamemangle$2#" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s#.+/(bar-)#@PACKAGE@-$1#" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s#.+/(baz-)#@PACKAGE@-$1#" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signatures and filenamemangle on all upstream tarballs [pattern 1]) +testWatch4WebNonNativeMUT_filenamemangle5b() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="foo $COMPONENTS" + WATCHLINE=' +opts="filenamemangle=s#.+/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)#$1-filenamemangle$2#, \ + pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s#.+/(bar-)#@PACKAGE@-$1#, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s#.+/(baz-)#@PACKAGE@-$1#, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, filenamemangle on all upstream tarballs [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle5c() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="foo $COMPONENTS" + WATCHLINE=' +opts="filenamemangle=s/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)/$1-filenamemangle$2/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s/(bar-)/@PACKAGE@-$1/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s/(baz-)/@PACKAGE@-$1/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT, signatures and filenamemangle on all upstream tarballs [pattern 2]) +testWatch4WebNonNativeMUT_filenamemangle5d() { + WATCHVER=4 + COMPONENTS="bar baz" + FILENAMEMANGLE="foo $COMPONENTS" + WATCHLINE=' +opts="filenamemangle=s/(@PACKAGE@-\d\S+)(@ARCHIVE_EXT@)/$1-filenamemangle$2/, \ + pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar, filenamemangle=s/(bar-)/@PACKAGE@-$1/, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz, filenamemangle=s/(baz-)/@PACKAGE@-$1/, pgpsigurlmangle=s/$/.asc/" \ + @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same' + helperWatch siteWebNonNativeMUT_filenamemangle +} + +# test normal web page (MUT with O main) +testWatch4WebNonNativeMUT0() { + WATCHVER=4 + COMPONENTS="foo bar baz" + FILEEXCLUDE=3 + MGZREPACK=xz + WATCHLINE=' +opts="component=foo,pgpsigurlmangle=s/$/.asc/" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ debian +opts="component=bar,pgpsigurlmangle=s/$/.asc/" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ same +opts="component=baz,pgpsigurlmangle=s/$/.asc/" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ same uupdate' + helperWatch siteWebNonNativeMUT +} + +# Group test without signatures +testWatch4WebNonNativeGroup() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=baz,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ group' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0+~3.0 +} + +# Group test with repack suffix +testWatch4WebNonNativeGroupRepackSuffix() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,repacksuffix=+ds,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=baz,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ group' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0+ds+~3.0 +} + +testWatch4WebNonNativeGroupRepackSuffix2() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="dversionmangle=auto,pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="dversionmangle=auto,component=bar,repacksuffix=~ds,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="dversionmangle=auto,component=baz,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ group' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0~ds+~3.0 +} + +# Group test with pgpsigurlmangle +testWatch4WebNonNativeGroupSigned() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpsigurlmangle=s/$/.asc/" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,pgpsigurlmangle=s/$/.asc/" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=baz,pgpsigurlmangle=s/$/.asc/" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ group' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0+~3.0 +} + +# Group test with pgpmode next/previous +testWatch4WebNonNativeGroupSignedNext() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + SIGMODE=ASC + WATCHLINE=' +opts="pgpmode=next" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="pgpmode=previous" @@@url@@@/ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@.asc previous +opts="component=bar,pgpmode=next" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,pgpmode=previous" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@.asc previous +opts="component=baz,pgpmode=next" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=baz,pgpmode=previous" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@.asc previous' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0+~3.0 +} + +testWatch4WebNonNativeGroupWithCompression() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,compression=xz,repack,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=baz,repack,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ group' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0+~3.0 +} + +testWatch4WebNonNativeGroupWithChecksum1() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,compression=xz,repack,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=baz,repack,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ checksum' + helperWatch siteWebNonNativeMUT 1.0 2.0+~3.0+~cs3.0 +} + +testWatch4WebNonNativeGroupWithChecksum2() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,compression=xz,repack,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ checksum +opts="component=baz,repack,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ checksum' + helperWatch siteWebNonNativeMUT 1.0 2.0+~cs6.0 +} + +testWatch4WebNonNativeGroupWithChecksumAndIgnore() { + WATCHVER=4 + COMPONENTS="bar baz" + FILEEXCLUDE=3 + UVERSION=2.0 + CMPVERSION=3.0 + WATCHLINE=' +opts="pgpmode=none" @@@url@@@ (?:.*)/foo@ANY_VERSION@@ARCHIVE_EXT@ group +opts="component=bar,compression=xz,repack,pgpmode=none" @@@url@@@ (?:.*)/bar@ANY_VERSION@@ARCHIVE_EXT@ checksum +opts="component=baz,repack,pgpmode=none" @@@url@@@ (?:.*)/baz@ANY_VERSION@@ARCHIVE_EXT@ ignore' + helperWatch siteWebNonNativeMUT 1.0 2.0+~cs3.0 +} + +. shunit2 diff --git a/test/test_uscan_online b/test/test_uscan_online new file mode 100755 index 0000000..47ecda2 --- /dev/null +++ b/test/test_uscan_online @@ -0,0 +1,50 @@ +#!/bin/sh + +# Copyright (C) 2012, Benjamin Drung <bdrung@debian.org> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -u + +# Operation mode +if test "${1:-}" = --installed; then + COMMAND="uscan --no-conf" + shift +else + top_srcdir=$(readlink -f "${0%/*}/..") + make -C "$top_srcdir/scripts" uscan mk-origtargz uupdate debchange + PATH="$top_srcdir/scripts:$PATH" + export PATH + PERL5LIB="$top_srcdir/lib" + export PERL5LIB + COMMAND="uscan --no-conf" +fi + +. "${0%/*}/shunit2-helper-functions.sh" + +found() { + runCommand "--report --watchfile ${0%/*}/uscan/$1 --package $2 --upstream-version $3" "$4" "" 0 +} + +testS3Bucket() { + local latest=$(curl -s http://s3.amazonaws.com/rds-downloads | \ + sed 's@\(</[A-Za-z]*>\)@\1\n@g' | grep '<Key>RDSCli-' | \ + sed 's@.*<Key>RDSCli-\([-0-9.]*\)\.zip</Key>.*@\1@g' | \ + sort -n | tail -n 1) + local result="uscan: Newest version of rdscli on remote site is ${latest}, local version is 1.4.007 +uscan: => Newer package available from: + => http://s3.amazonaws.com/rds-downloads/RDSCli-${latest}.zip" + found "s3bucket" "rdscli" "1.4.007" "$result" +} + +. shunit2 diff --git a/test/test_uscan_svn b/test/test_uscan_svn new file mode 100755 index 0000000..fdc3c2d --- /dev/null +++ b/test/test_uscan_svn @@ -0,0 +1,201 @@ +#!/bin/bash + +# Copyright (C) 2018, Xavier <yadd@debian.org> +# 2019-2020, Andrius Merkys <merkys@debian.org> +# +# 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 3 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. +# +# On Debian systems, the complete text of the GNU General Public License +# version 3 can be found in the /usr/share/common-licenses/GPL-3 file. + +set -u +#set -x + +DEB_HOST_OS="$(dpkg-architecture -qDEB_HOST_ARCH_OS)" +if [ "$DEB_HOST_OS" = "kfreebsd" ]; then + # kbsd has a non-working semaphore, that is needed here. + echo "This test is not supported on $(dpkg-architecture -qDEB_HOST_ARCH), skipping" + exit 0 +fi +DEB_HOST_ARCH="$(dpkg-architecture -qDEB_HOST_ARCH)" +if [ "$DEB_HOST_ARCH" = "i386" ]; then + echo "To \"help\" Ubuntu that has a fondamentally broken i386 (so that we can't depend on svn), this test is simply skipped on i386." + exit 0 +fi + +TESTTYPE=Svn +. ./lib_test_uscan + +COMMAND="chronic_sh uscan --no-conf --compression=xz --dehs" + +# prevent the local from messing with this test +export HOME="" +export XDG_CONFIG_HOME="" + +# comment out for debug +#COMMAND="$COMMAND --verbose" +#COMMAND="$COMMAND --debug" + +cleanup(){ + rm -rf "$TEMP_PKG_DIR" +} + +spawnSvnRepo(){ + mkdir -p "$TEMP_PKG_DIR/repo" + (cd "$TEMP_PKG_DIR/repo" || exit 1 + chronic_sh svnadmin create .) + mkdir -p "$TEMP_PKG_DIR/working-copy" + (cd "$TEMP_PKG_DIR/working-copy" || exit 1 + chronic_sh svn checkout "file:///$TEMP_PKG_DIR/repo" . + chronic_sh mkdir trunk tags + touch trunk/changelog trunk/file.c + chronic_sh svn add trunk tags + chronic_sh svn commit -m 'Init' + export TZ=UTC + for version in 1.0 2.0; do + echo "# Version $version" >> trunk/file.c + cat >> trunk/changelog <<END +Version $version + +END + chronic_sh faketime -f '2000-01-01 12:34:56' svn commit -m "Releasing $version" + chronic_sh faketime -f '2000-01-01 12:34:56' svn copy ^/trunk "^/tags/v$version" -m "Version $version" + done) +} + +trap cleanup EXIT + +containsName(){ + echo "$1" | grep -F -q "$2" + echo $? +} + +# shellcheck source=shunit2-helper-functions.sh +. "${0%/*}/shunit2-helper-functions.sh" + +PKG=foo + +makeDebianDir() { + WATCHARGS=$1 + TEMP_PKG_DIR=$(mktemp -d --tmpdir="$SHUNIT_TMPDIR" uscan_svn.XXXXXX) + if [ -z "$TEMP_PKG_DIR" ]; then + echo "Failed to create temporary directory" >&2 + exit 1 + fi + mkdir -p "$TEMP_PKG_DIR/$PKG/debian/source" + spawnSvnRepo + + cat <<END > "$TEMP_PKG_DIR/$PKG/debian/watch" +version=4 +opts="mode=svn,$WATCHARGS" \ +file:///$TEMP_PKG_DIR/repo/tags v([\\d\\.]+)\/ debian +END + + cat <<END > "$TEMP_PKG_DIR/$PKG/debian/changelog" +$PKG (0-1) unstable; urgency=low + + * Initial release + + -- Joe Developer <jd@debian.org> Mon, 02 Nov 2013 22:21:31 -0100 +END + echo '3.0 (quilt)' > "$TEMP_PKG_DIR/$PKG/debian/source/format" +} + +makeDebianDirHead() { + WATCHARGS=$1 + makeDebianDir "$WATCHARGS" + cat <<END > "$TEMP_PKG_DIR/$PKG/debian/watch" +version=4 +opts="mode=svn,$WATCHARGS" \ +file:///$TEMP_PKG_DIR/repo/trunk HEAD +END +} + +helperLaunch() { + WATCHARGS=$1 + ARG="${2:-}" + if test "$ARG" = "HEAD"; then + makeDebianDirHead "$WATCHARGS" + else + makeDebianDir "$WATCHARGS" + fi + ( cd "$TEMP_PKG_DIR/$PKG" || exit 1 ; $COMMAND --watchfile=debian/watch ) + assertEquals "uscan: exit_code!=0 but exit_code=0" "0" "$?" +} + +helperLaunchFail() { + WATCHARGS=$1 + ARG="${2:-}" + if test "$ARG" = "HEAD"; then + makeDebianDirHead "$WATCHARGS" + else + makeDebianDir "$WATCHARGS" + fi + # discard output as it's expected to fail + ( cd "$TEMP_PKG_DIR/$PKG" || exit 1 ; $COMMAND --watchfile=debian/watch > /dev/null) + assertEquals "uscan: exit_code!=2 but exit_code=2" "2" "$?" +} + +testSvn() { + helperLaunch "pgpmode=none" + TARBALL="${PKG}_2.0.orig.tar.xz" + CHECKSUM=$(sha1sum "$TEMP_PKG_DIR/${PKG}-2.0.tar.xz" | awk '{print $1}') + assertTrue 'downloaded tarfile not present' "[ -f '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$TEMP_PKG_DIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$TEMP_PKG_DIR/$TARBALL' ]" + if [ "$CHECKSUM" != 'bd4a60786013848e402bcf20db211fd465afeda5' ]; then + set -x + echo "Copying the faulty tarball to the artefact directory, if available..." + if [ -n "${AUTOPKGTEST_ARTIFACTS:-}" ] && [ -d "$AUTOPKGTEST_ARTIFACTS" ]; then + cp -v "$TEMP_PKG_DIR/${PKG}-2.0.tar.xz" "$AUTOPKGTEST_ARTIFACTS"/ + fi + set +x + fi + assertTrue 'checksums do not match' "[ '${CHECKSUM}' = 'bd4a60786013848e402bcf20db211fd465afeda5' ]" + cleanup +} + +testSvnPgpmodeDefault() { + helperLaunch "pgpmode=default" + TARBALL="${PKG}_2.0.orig.tar.xz" + assertTrue 'downloaded tarfile not present' "[ -f '$TEMP_PKG_DIR/${PKG}-2.0.tar.xz' ]" + assertTrue 'pristine tarball is not created' "[ -f '$TEMP_PKG_DIR/$TARBALL' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$TEMP_PKG_DIR/$TARBALL' ]" + cleanup +} + +testSvnPgpmodeNext() { + helperLaunchFail "pgpmode=next" + cleanup +} + +testSvnHead() { + helperLaunch "pgpmode=none" HEAD + ORIG="$TEMP_PKG_DIR/foo_0.0~svn4.orig.tar.xz" + UPSTREAM="$TEMP_PKG_DIR/foo-0.0~svn4.tar.xz" + assertTrue 'downloaded tarfile not present' "[ -f '$UPSTREAM' ]" + assertTrue 'pristine tarball is not created' "[ -f '$ORIG' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$ORIG' ]" + cleanup +} + +testSvnHeadMangle() { + helperLaunch "pgpmode=none,uversionmangle=s/^[^~]+/1.23.45/" HEAD + ORIG="$TEMP_PKG_DIR/foo_1.23.45~svn4.orig.tar.xz" + UPSTREAM="$TEMP_PKG_DIR/foo-1.23.45~svn4.tar.xz" + assertTrue 'downloaded tarfile not present' "[ -f '$UPSTREAM' ]" + assertTrue 'pristine tarball is not created' "[ -f '$ORIG' ]" + assertTrue 'pristine tarball is a symlink' "[ -L '$ORIG' ]" + cleanup +} + +# shellcheck disable=SC1091 +. shunit2 diff --git a/test/test_wrap-and-sort b/test/test_wrap-and-sort new file mode 100755 index 0000000..ac6bdab --- /dev/null +++ b/test/test_wrap-and-sort @@ -0,0 +1,50 @@ +#!/bin/sh + +# Copyright (C) 2022, Niels Thykier <niels@thykier.net> +# +# 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/>. + +set -u + + +WORK_DIR="$(readlink -f "${0%/*}")" +if test "${1:-}" = --installed; then + wrap_and_sort="wrap-and-sort " + shift +else + wrap_and_sort="${WORK_DIR}/../scripts/wrap-and-sort" +fi + +. "${WORK_DIR}/test_helper.sh" + +oneTimeSetUp() { + TEMP_DIR=$(mktemp -d -p "$SHUNIT_TMPDIR" wrap-and-sort.XXXXX) +} + +# Run as `prepare_and_run_wrap_and_sort <test-name> [args-for-wrap-and-sort]` +prepare_and_run_wrap_and_sort() { + TEST_NAME="${1}" + TEST_DIR="${TEMP_DIR}/${TEST_NAME}" + + mkdir "${TEST_DIR}" + cp -a "${WORK_DIR}/wrap-and-sort/${TEST_NAME}/in/"* "$TEST_DIR/" || exit 1 + assertPasses $wrap_and_sort -d "$TEST_DIR" + assertPasses diff -Nuarp "${WORK_DIR}/wrap-and-sort/${TEST_NAME}/out" "${TEST_DIR}" +} + +test_install_comments() { + prepare_and_run_wrap_and_sort 'install-comments' +} + +. shunit2 |