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