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