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