chiark / gitweb /
Avoid use of "my $_", which is not portable
[dgit.git] / tests / lib
1 #
2
3 exec 2>&1
4 set -x
5 set -o pipefail
6
7 . tests/lib-core
8
9 t-set-intree
10
11 : ${DGIT_TEST_DEBUG:=-D}
12 export DGIT_TEST_DEBUG
13
14 root=`pwd`
15 troot=$root/tests
16 testname="${DGIT_TEST_TESTNAME-${0##*/}}"
17
18 tmp=$ADTTMP
19 if [ x"$tmp" = x ]; then
20         mkdir -p tests/tmp
21         tmp=tests/tmp/$testname
22         rm -rf $tmp
23         mkdir $tmp
24 fi
25 cd $tmp
26
27 tmp=`pwd`
28
29 t-set-using-tmp
30
31 ln -f $troot/ssh ssh
32
33 mkdir -p $tmp/gnupg
34 cp $troot/gnupg/* $tmp/gnupg
35 chmod go-rw $tmp/gnupg/*
36
37 mkdir -p $tmp/incoming
38 cat <<END >$tmp/dput.cf
39 [test-dummy]
40 method                  = local
41 incoming                = $tmp/incoming
42 run_dinstall            = 0
43 END
44
45 t-expect-fail () {
46         local mpat="$1"; shift
47
48         local grepper=fgrep
49         case "$mpat" in
50         [A-Z]:*)
51                 case "$mpat" in
52                 E:*)    grepper=egrep   ;;
53                 F:*)    grepper=fgrep   ;;
54                 *)      fail "bad mpat prefix in $mpat";;
55                 esac
56                 mpat=${mpat#[A-Z]:}
57                 ;;
58         esac
59
60         set +o pipefail
61         LC_MESSAGES=C "$@" 2>&1 | tee $tmp/t.output
62         local ps="${PIPESTATUS[*]}"
63         set -o pipefail
64
65         case $ps in
66         "0 0")  fail "command unexpectedly succeeded (instead of: $mpat)" ;;
67         *" 0")  ;;
68         *)      fail "tee failed"  ;;
69         esac
70
71         $grepper -e "$mpat" $tmp/t.output ||
72                 fail "error message not found"
73 }
74
75 t-expect-push-fail () {
76         local mpat="$1"; shift
77
78         local triedpush=`git rev-parse HEAD`
79
80         t-reporefs pre-push
81         t-expect-fail "$mpat"  "$@"
82         t-reporefs post-push
83         diff $tmp/show-refs.{pre,post}-push
84
85         t-git-objects-not-present '' $triedpush
86
87         eval "$t_expect_push_fail_hook"
88 }
89
90 t-git-objects-not-present () {
91         # t-git-objects-not-present GITDIR|'' OBJID [...]
92         # specifying '' means the repo for package $p
93         local gitdir="${1-$tmp/git/$p.git}"
94         local obj
95         if ! [ -e "$gitdir" ]; then return; fi
96         for obj in "$@"; do
97                 GIT_DIR=$gitdir \
98                 t-expect-fail 'unable to find' \
99                 git cat-file -t $obj
100         done
101 }
102
103 t-reporefs () {
104         local whichoutput=$1; shift
105         local outputfile="$tmp/show-refs.$whichoutput"
106         (set -e
107          exec >"$outputfile"
108          if test -d $tmp/git/$p.git; then
109                 cd $tmp/git/$p.git
110                 git show-ref |sort
111         fi)
112 }
113
114 t-untar () {
115         local tarfile=$1.tar
116         local edittree=$1.edit
117         if test -d "$edittree"; then
118                 cp -al "$edittree"/* .
119         else
120                 tar xf "$tarfile"
121         fi
122 }
123
124 t-worktree () {
125         rm -rf $p
126         t-untar $troot/worktrees/${p}_$1
127 }
128
129 t-git () {
130         p=$1
131         v=$2
132         mkdir -p $tmp/git
133         local gs=$troot/git-srcs/${p}_$v.git
134         (set -e; cd $tmp/git; t-untar $gs)
135 }
136
137 t-git-none () {
138         mkdir -p $tmp/git
139         (set -e; cd $tmp/git; tar xf $troot/git-template.tar)
140 }
141
142 t-has-ancestor () {
143         local now=`git rev-parse HEAD`
144         local ancestor=`git rev-parse $1^{}`
145         local mbase=`git merge-base $ancestor $now`
146         if [ x$mbase != x$ancestor ]; then
147                 fail "not ff $ancestor..$now, $mbase != $ancestor"
148         fi
149 }
150
151 t-prep-newpackage () {
152         p=$1
153         v=$2
154         t-archive-none $p
155         t-git-none
156         t-worktree $v
157         cd $p
158         if ! git-show-ref --verify --quiet refs/heads/master; then
159                 git branch -m dgit/sid master
160                 git remote rm dgit
161         fi
162         cd ..
163 }
164
165 t-archive-none () {
166         p=$1
167         mkdir -p $tmp/aq $tmp/mirror/pool/main
168
169         local suite=sid
170
171         >$tmp/aq/package.$suite.$p
172         t-archive-updated $suite $p
173
174         >$tmp/aq/package.new.$p
175         t-archive-updated new $p
176
177         ln -s sid $tmp/aq/dsc_in_suite/unstable
178         cat <<'END' >$tmp/aq/suites
179 [
180    {
181       "archive" : "ftp-master",
182       "codename" : "sid",
183       "components" : [
184          "main",
185          "contrib",
186          "non-free"
187       ],
188       "name" : "unstable",
189       "dakname" : "unstable"
190    }
191 ]
192 END
193 }
194
195 t-archive-updated () {
196         local suite=$1
197         local p=$2
198         local suitedir=$tmp/aq/dsc_in_suite/$suite
199         mkdir -p $suitedir
200         perl <$tmp/aq/package.$suite.$p >$suitedir/$p -wne '
201                 use JSON;
202                 use strict;
203                 our @v;
204                 m{^(\S+) (\w+) ([^ \t/]+)/(\S+)} or die;
205                 push @v, {
206                         "version" => "$1",
207                         "sha256sum" => "$2",
208                         "component" => "$3",
209                         "filename" => "$4",
210                 };
211                 END {
212                         print to_json \@v or die $!;
213                 }
214         '
215 }
216
217 t-archive-process-incoming () {
218         local suite=$1
219         mv $tmp/incoming/${p}_${v}[._]* $tmp/mirror/pool/main/
220         t-archive-query "$suite"
221 }
222
223 t-archive-query () {
224         local suite=${1-sid}
225         local dscf=main/${p}_${v}.dsc
226         local sha=`sha256sum <$tmp/mirror/pool/$dscf`
227         echo "${v} ${sha%  -} $dscf" >>$tmp/aq/package.$suite.${p}
228         t-archive-updated $suite $p
229 }
230
231 t-archive () {
232         t-archive-none $1
233         v=$2
234         local dscf=${p}_$2.dsc
235         rm -f $tmp/mirror/pool/main/${p}_*
236         ln $troot/pkg-srcs/${p}_${2%-*}* $tmp/mirror/pool/main/
237         t-archive-query
238         rm -rf $tmp/extract
239         mkdir $tmp/extract
240         (set -e; cd $tmp/extract; dpkg-source -x ../mirror/pool/main/$dscf)
241 }
242
243 t-git-dir-time-passes () {
244         touch -d 'last year' $tmp/git/$p.git
245 }
246
247 t-git-dir-check () {
248         local gitdir=$tmp/git/$p.git
249         case "$1" in
250         enoent)
251                 if test -e "$gitdir"; then fail "$gitdir exists"; fi
252                 return
253                 ;;
254         public) wantstat='7[75]5' ;;
255         secret) wantstat='7[70]0' ;;
256         *)      fail "$1 t-git-dir-check ?" ;;
257         esac
258         gotstat=`stat -c%a $gitdir`
259         case "$gotstat" in
260         *$wantstat) return ;;
261         *)      fail "$gitdir has mode $gotstat, expected $wantstat" ;;
262         esac
263 }
264
265 t-rm-dput-dropping () {
266         rm -f $tmp/${p}_${v}_*.upload
267 }
268
269 t-dgit () {
270         local dgit=${DGIT_TEST-dgit}
271         : '
272 {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{'
273         $dgit --dgit=$dgit --dget:-u --dput:--config=$tmp/dput.cf \
274                 -dtest-dummy $DGIT_TEST_OPTS $DGIT_TEST_DEBUG \
275                 -k39B13D8A "$@"
276         : '}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
277 '
278 }
279
280 t-diff-nogit () {
281         diff --exclude=.git --exclude=.pc -ruN $*
282 }
283
284 t-cloned-fetched-good () {
285         t-diff-nogit ../extract/$p-${v%-*} .
286         t-clean-on-branch dgit/sid
287         t-refs-same-start
288         t-refs-same \
289                 refs/heads/dgit/sid \
290                 refs/remotes/dgit/dgit/sid
291         t-refs-notexist refs/dgit/unstable refs/remotes/dgit/dgit/unstable
292 }
293
294 t-output () {
295         printf "%s\n" "$1" >$tmp/t.want
296         shift
297         "$@" >$tmp/t.got
298         diff $tmp/t.want $tmp/t.got
299 }
300
301 t-clean-on-branch () {
302         t-output "## $1" git status -b --porcelain
303 }
304
305 t-git-get-ref-exact () {
306         local ref=$1
307         # does not dereference, unlike t-git-get-ref
308         case "$ref" in
309         refs/*) ;;
310         *) fail "t-git-get-ref-exact bad $ref" ;;
311         esac
312         git for-each-ref --format='%(objectname)' "[r]efs/${ref#refs/}"
313 }
314
315 t-git-get-ref () {
316         local ref=$1
317         case "$ref" in
318         refs/*) ;;
319         *) fail "t-git-get-ref bad $ref" ;;
320         esac
321         (git show-ref -d $1 || test $? = 1) | perl -ne '
322                 $x = $1 if m#^(\w+) \Q'$1'\E(?:\^\{\})?$#;
323                 END { print "$x\n" if length $x; }
324         '
325 }
326
327 t-ref-same () {
328         local name="$1"
329         local val=`t-git-get-ref $name`
330         t-ref-same-val "$name" $val
331 }
332
333 t-ref-head () {
334         local val=`git rev-parse HEAD`
335         t-ref-same-val HEAD $val
336 }
337
338 t-ref-same-val () {
339         local name="$1"
340         local val=$2
341         case "$t_ref_val" in
342         '')             ;;
343         "$val")         ;;
344         *)              fail "ref varies: $name: $val != $t_ref_val" ;;
345         esac
346         t_ref_val="$val"
347 }
348
349 t-refs-same-start () {
350         t_ref_val=''
351 }
352
353 t-refs-same () {
354         local g
355         for g in $*; do
356                 t-ref-same $g
357         done
358 }
359
360 t-refs-notexist () {
361         local val
362         for g in $*; do
363                 val=`t-git-get-ref $g >$tmp/t.refx`
364                 if [ "x$val" != x ]; then
365                         fail "ref $g unexpectedly exists ($val)"
366                 fi
367         done
368 }
369
370 t-v-tag () {
371         echo refs/tags/debian/${v//\~/_}
372 }
373
374 t-pushed-good () {
375         local branch=$1
376         t-ref-dsc-dgit
377         t-refs-same \
378                 refs/heads/$branch \
379                 `t-v-tag` \
380                 refs/remotes/dgit/dgit/sid
381         t-refs-notexist \
382                 refs/heads/dgit/unstable \
383                 refs/remotes/dgit/dgit/unstable
384         (set -e; cd $tmp/git/$p.git
385          t-refs-same \
386                 refs/dgit/sid \
387                 `t-v-tag`
388          t-refs-notexist \
389                 refs/dgit/unstable
390         )
391         git verify-tag `t-v-tag`
392 }
393
394 t-822-field () {
395         local file=$1
396         local field=$2
397         perl -e '
398                 use Dpkg::Control::Hash;
399                 my $h = new Dpkg::Control::Hash allow_pgp=>1;
400                 $h->parse(\*STDIN,"'"$file"'");
401                 my $val = $h->{"'$field'"},"\n";
402                 die "'"$file $field"'" unless defined $val;
403                 print $val,"\n";
404         ' <$file
405 }
406
407 t-stunt-envvar () {
408         local var=$1
409         local tstunt=$2
410         eval '
411                 case "'$var'" in
412                 "$tstunt:"*)    ;;
413                 *":$tstunt:"*)  ;;
414                 *)              '$var'="$tstunt:$'$var'" ;;
415                 esac
416         '
417 }
418
419 t-tstunt () {
420         local tstunt=$tmp/tstunt
421         t-stunt-envvar PATH $tstunt
422         t-stunt-envvar PERLLIB $tstunt
423         local f
424         for f in "$@"; do
425                 f="./$f"
426                 local d="$tstunt/${f%/*}"
427                 mkdir -p $d
428                 ln -sf "$troot/tstunt/$f" "$d"/.
429         done
430 }
431
432 t-tstunt-parsechangelog () {
433         t-tstunt dpkg-parsechangelog Dpkg/Changelog/Parse.pm
434 }
435
436 t-prep-mergechangelogs () {
437         local b=merge.dpkg-mergechangelogs
438         git config $b.name 'debian/changelog merge driver'
439         git config $b.driver 'dpkg-mergechangelogs -m %O %A %B %A'
440         mkdir -p .git/info
441         echo >>.git/info/attributes \
442                 'debian/changelog merge=dpkg-mergechangelogs'
443 }
444
445 t-ref-dsc-dgit () {
446         local dsc=${p}_${v}.dsc
447         local val=`t-822-field $tmp/incoming/$dsc Dgit`
448         perl -e '$_=shift @ARGV; die "$dsc Dgit $_ ?" unless m/^\w+\b/;' "$val"
449         t-ref-same-val $dsc "$val"
450 }
451
452 t-apply-diff () {
453         local v1=$1
454         local v2=$2
455         (cd $troot/pkg-srcs;
456          debdiff ${p}_${v1}.dsc ${p}_${v2}.dsc || test $? = 1) \
457          | patch -p1 -u
458 }
459
460 t-commit () {
461         local msg=$1
462         v=1.$revision
463         dch -v$v --distribution unstable "$1"
464         git add debian/changelog
465         debcommit
466         revision=$(( $revision + 1 ))
467 }
468
469 t-git-config () {
470         git config --global "$@"
471 }
472
473 t-drs () {
474         export DGIT_TEST_TROOT=$troot
475  t-git-config dgit-distro.test-dummy.git-url "ext::$troot/drs-git-ext %S "
476  t-git-config dgit-distro.test-dummy.git-check true
477  t-git-config dgit-distro.test-dummy.git-create true
478         cp $troot/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/.
479         cp $troot/suites $tmp/.
480
481         drs_dispatch=$tmp/distro=test-dummy
482         mkdir $drs_dispatch
483
484         if [ "x$DGIT_TEST_INTREE" != x ]; then
485                 ln -sf "$DGIT_TEST_INTREE" $drs_dispatch/dgit-live
486         fi
487
488         ln -sf $tmp/git $drs_dispatch/repos
489         ln -sf $tmp/suites $tmp/dm.txt $drs_dispatch/
490         mkdir -p $drs_dispatch/keyrings
491         ln -sf $tmp/dd.gpg $drs_dispatch/keyrings/debian-keyring.gpg
492         ln -sf $tmp/dm.gpg $drs_dispatch/keyrings/debian-maintainers.gpg
493         ln -sf /bin/true $drs_dispatch/policy-hook
494 }
495
496 t-dsd () {
497         t-drs
498  t-git-config dgit-distro.test-dummy.ssh "$troot/dsd-ssh"
499  t-git-config dgit-distro.test-dummy.git-check ssh-cmd
500  t-git-config dgit-distro.test-dummy.git-create true
501  t-git-config dgit-distro.test-dummy.git-url \
502                 "ext::$troot/dsd-ssh X %S /dgit/test-dummy/repos"
503
504  t-git-config dgit-distro.test-dummy.diverts.drs /drs
505  t-git-config dgit-distro.test-dummy/drs.ssh "$troot/ssh"
506  t-git-config dgit-distro.test-dummy/drs.git-url $tmp/git
507  t-git-config dgit-distro.test-dummy/drs.git-check ssh-cmd
508  t-git-config dgit-distro.test-dummy/drs.git-create ssh-cmd
509
510         echo 'no-such-package* drs' >$drs_dispatch/diverts
511 }
512
513 t-policy-admin () {
514         ${DGIT_INFRA_PFX}dgit-repos-admin-debian --repos $tmp/git "$@"
515 }
516
517 t-policy () {
518         local policyhook=$1
519         ln -sf ${DGIT_INFRA_PFX}$policyhook \
520                 $drs_dispatch/policy-hook
521 }
522
523 t-debpolicy () {
524         t-dsd
525         t-policy dgit-repos-policy-debian
526
527         mkdir $tmp/git
528         t-policy-admin create-db
529 }
530
531 t-policy-periodic () {
532         ${DGIT_REPOS_SERVER_TEST-dgit-repos-server} \
533                 test-dummy $drs_dispatch '' --cron
534 }
535
536 t-chain-test () {
537         local ct=$1
538         local d=${0%/*}
539         cd $root
540         export DGIT_TEST_TESTNAME="$testname"
541         export ADTTMP=$tmp
542         exec "$d/$ct"
543 }       
544
545 t-alt-test () {
546         local t=${0##*/}
547         t-${t%%-*}
548         t-chain-test "${t#*-}"
549 }