X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=tests%2Flib;h=81accebf0f6f11d53639af725298416606102e33;hp=e960c1c62c33f60c76a27f83cd212aac0b8fcc2a;hb=441cf15ffbafea7aa6be4cc04bb0085c8d79063e;hpb=d05936fa35e8fccc8b9eead88379fcdaa2021277 diff --git a/tests/lib b/tests/lib index e960c1c6..81accebf 100644 --- a/tests/lib +++ b/tests/lib @@ -2,14 +2,33 @@ exec 2>&1 set -x +set -o pipefail . tests/lib-core +. tests/lib-restricts + +t-report-failure () { + set +x + rc=$1 + cat <&2 +TEST FAILED +funcs: ${FUNCNAME[*]} +lines: ${BASH_LINENO[*]} +files: ${BASH_SOURCE[*]} +END + exit 16 +} + +trap 'test $? = 0 || t-report-failure' EXIT t-set-intree -: ${DGIT_TEST_DEBUG:=-D} +: ${DGIT_TEST_DEBUG=-D} export DGIT_TEST_DEBUG +export GIT_COMMITTER_DATE='1440253867 +0100' +export GIT_AUTHOR_DATE='1440253867 +0100' + root=`pwd` troot=$root/tests testname="${DGIT_TEST_TESTNAME-${0##*/}}" @@ -17,6 +36,7 @@ testname="${DGIT_TEST_TESTNAME-${0##*/}}" tmp=$ADTTMP if [ x"$tmp" = x ]; then mkdir -p tests/tmp + tmpbase=$troot/tmp tmp=tests/tmp/$testname rm -rf $tmp mkdir $tmp @@ -27,12 +47,16 @@ tmp=`pwd` t-set-using-tmp +env -0 >$tmp/.save-env + ln -f $troot/ssh ssh mkdir -p $tmp/gnupg cp $troot/gnupg/* $tmp/gnupg chmod go-rw $tmp/gnupg/* +export DEBCHANGE_VENDOR=dpkg + mkdir -p $tmp/incoming cat <$tmp/dput.cf [test-dummy] @@ -41,18 +65,96 @@ incoming = $tmp/incoming run_dinstall = 0 END +: ${tagpfx:=test-dummy} +: ${suitespecs:=sid:unstable} + +t-git-next-date () { + GIT_COMMITTER_DATE="$(( ${GIT_COMMITTER_DATE%% *} + 1 )) ${GIT_COMMITTER_DATE#* }" + GIT_AUTHOR_DATE="$GIT_COMMITTER_DATE" +} + t-expect-fail () { local mpat="$1"; shift + + set +o pipefail LC_MESSAGES=C "$@" 2>&1 | tee $tmp/t.output - test ${PIPESTATUS[0]} != 0 - egrep "$mpat" $tmp/t.output ||false + local ps="${PIPESTATUS[*]}" + set -o pipefail + + case $ps in + "0 0") fail "command unexpectedly succeeded (instead of: $mpat)" ;; + *" 0") ;; + *) fail "tee failed" ;; + esac + + t-grep-mpat "$mpat" $tmp/t.output +} + +t-grep-mpat () { + local mpat="$1" + local file="$2" + + local grepper=fgrep + case "$mpat" in + [A-Z]:*) + case "$mpat" in + E:*) grepper=egrep ;; + F:*) grepper=fgrep ;; + *) fail "bad mpat prefix in $mpat";; + esac + mpat=${mpat#[A-Z]:} + ;; + esac + + $grepper -e "$mpat" "$file" || + fail "message not found" +} + +t-expect-push-fail () { + local mpat="$1"; shift + + local triedpush=`git rev-parse HEAD` + + t-reporefs pre-push + t-expect-fail "$mpat" "$@" + t-reporefs post-push + diff $tmp/show-refs.{pre,post}-push + + t-git-objects-not-present '' $triedpush + + eval "$t_expect_push_fail_hook" +} + +t-git-objects-not-present () { + # t-git-objects-not-present GITDIR|'' OBJID [...] + # specifying '' means the repo for package $p + local gitdir="${1-$dgitrepo}" + local obj + if ! [ -e "$gitdir" ]; then return; fi + for obj in "$@"; do + GIT_DIR=$gitdir \ + t-expect-fail 'unable to find' \ + git cat-file -t $obj + done +} + +t-reporefs () { + local whichoutput=$1; shift + local whichrepo=${1-$dgitrepo} + local outputfile="$tmp/show-refs.$whichoutput" + (set -e + exec >"$outputfile" + if test -d $whichrepo; then + cd $whichrepo + git show-ref |sort + fi) } t-untar () { local tarfile=$1.tar local edittree=$1.edit if test -d "$edittree"; then - cp -al "$edittree"/* . + cp -a "$edittree"/* . else tar xf "$tarfile" fi @@ -63,8 +165,13 @@ t-worktree () { t-untar $troot/worktrees/${p}_$1 } -t-git () { +t-select-package () { p=$1 + dgitrepo=$tmp/git/$p.git +} + +t-git () { + t-select-package $1 v=$2 mkdir -p $tmp/git local gs=$troot/git-srcs/${p}_$v.git @@ -76,23 +183,27 @@ t-git-none () { (set -e; cd $tmp/git; tar xf $troot/git-template.tar) } +t-git-merge-base () { + git merge-base $1 $2 || test $? = 1 +} + t-has-ancestor () { local now=`git rev-parse HEAD` local ancestor=`git rev-parse $1^{}` - local mbase=`git merge-base $ancestor $now` + local mbase=`t-git-merge-base $ancestor $now` if [ x$mbase != x$ancestor ]; then fail "not ff $ancestor..$now, $mbase != $ancestor" fi } t-prep-newpackage () { - p=$1 + t-select-package $1 v=$2 t-archive-none $p t-git-none t-worktree $v cd $p - if ! git-show-ref --verify --quiet refs/heads/master; then + if ! git show-ref --verify --quiet refs/heads/master; then git branch -m dgit/sid master git remote rm dgit fi @@ -100,31 +211,44 @@ t-prep-newpackage () { } t-archive-none () { - p=$1 - mkdir -p $tmp/aq $tmp/mirror/pool/main + t-select-package $1 + mkdir -p $tmp/aq/dsc_in_suite $tmp/mirror/pool/main - local suite=sid + : >$tmp/aq/suites + local jsondelim="[" - >$tmp/aq/package.$suite.$p - t-archive-updated $suite $p + local suitespec + for suitespec in $suitespecs; do + local suite=${suitespec%%:*} + local sname=${suitespec#*:} + + >$tmp/aq/package.$suite.$p + t-archive-updated $suite $p - >$tmp/aq/package.new.$p - t-archive-updated new $p + >$tmp/aq/package.new.$p + t-archive-updated new $p - ln -s sid $tmp/aq/dsc_in_suite/unstable - cat <<'END' >$tmp/aq/suites -[ + ln -s $suite $tmp/aq/dsc_in_suite/$sname + + cat <>$tmp/aq/suites +$jsondelim { "archive" : "ftp-master", - "codename" : "sid", + "codename" : "$suite", "components" : [ "main", "contrib", "non-free" ], - "name" : "unstable", - "dakname" : "unstable" - } + "name" : "$sname", + "dakname" : "$sname" +END + + jsondelim=" }," + + done + cat <>$tmp/aq/suites + } ] END } @@ -146,7 +270,8 @@ t-archive-updated () { "filename" => "$4", }; END { - print to_json \@v or die $!; + my $json = JSON->new->canonical(); + print $json->encode(\@v) or die $!; } ' } @@ -178,11 +303,11 @@ t-archive () { } t-git-dir-time-passes () { - touch -d 'last year' $tmp/git/$p.git + touch -d 'last year' $dgitrepo } t-git-dir-check () { - local gitdir=$tmp/git/$p.git + local gitdir=$dgitrepo case "$1" in enoent) if test -e "$gitdir"; then fail "$gitdir exists"; fi @@ -205,6 +330,7 @@ t-rm-dput-dropping () { t-dgit () { local dgit=${DGIT_TEST-dgit} + pwd : ' {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{' $dgit --dgit=$dgit --dget:-u --dput:--config=$tmp/dput.cf \ @@ -218,6 +344,15 @@ t-diff-nogit () { diff --exclude=.git --exclude=.pc -ruN $* } +t-files-notexist () { + local f + for f in "$@"; do + if [ -e $f ]; then + fail "$f exists!" + fi + done +} + t-cloned-fetched-good () { t-diff-nogit ../extract/$p-${v%-*} . t-clean-on-branch dgit/sid @@ -239,18 +374,88 @@ t-clean-on-branch () { t-output "## $1" git status -b --porcelain } +t-setup-done () { + local savevars=$1 + local savedirs=$2 + local importeval=$3 + + exec 4>$tmp/IMPORT.new + + local vn + for vn in $savevars; do + perl >&4 -I. -MDebian::Dgit -e ' + printf "%s=%s\n", $ARGV[0], shellquote $ARGV[1] + ' $vn "$(eval "printf '%s\n' \"\$$vn\"")" + done + + (set -e; cd $tmp; tar cf IMPORT.tar $savedirs) + + printf >&4 "\n%s\n" "$importeval" + + mv -f $tmp/IMPORT.new $tmp/IMPORT +} + +t-setup-import () { + local setupname=$1 + + if [ "x$tmpbase" = x ]; then + # ADTTMP was set on entry to tests/lib, so we + # are not sharing tmp area between tests + setupsrc="$tmp" + else + setupsrc="$tmpbase/$setupname" + fi + + local simport="$setupsrc/IMPORT" + + if ! [ -e "$simport" ]; then + with-lock-ex -w "$simport.lock" \ + xargs -0 -a $tmp/.save-env \ + bash -xec ' + cd "$1"; shift + setupname="$1"; shift + simport="$1"; shift + if [ -e "$simport" ]; then exit 0; fi + env - "$@" \ + "tests/setup/$setupname" + ' x "$root" "$setupname" "$simport" + fi + + if [ "x$setupsrc" != "x$tmp" ]; then + (set -e; cd $tmp; tar xf "$simport.tar") + fi + + . "$simport" +} + +t-git-get-ref-exact () { + local ref=$1 + # does not dereference, unlike t-git-get-ref + case "$ref" in + refs/*) ;; + *) fail "t-git-get-ref-exact bad $ref" ;; + esac + git for-each-ref --format='%(objectname)' "[r]efs/${ref#refs/}" +} + t-git-get-ref () { local ref=$1 case "$ref" in refs/*) ;; *) fail "t-git-get-ref bad $ref" ;; esac - git show-ref -d $1 | perl -ne ' + (git show-ref -d $1 || test $? = 1) | perl -ne ' $x = $1 if m#^(\w+) \Q'$1'\E(?:\^\{\})?$#; END { print "$x\n" if length $x; } ' } +t-ref-same-exact () { + local name="$1" + local val=`t-git-get-ref-exact $name` + t-ref-same-val "$name" $val +} + t-ref-same () { local name="$1" local val=`t-git-get-ref $name` @@ -268,7 +473,8 @@ t-ref-same-val () { case "$t_ref_val" in '') ;; "$val") ;; - *) fail "ref varies: $name: $val != $t_ref_val" ;; + *) fail "ref varies: $name:\ + ${val:-nothing} != ${t_ref_val:-nothing}" ;; esac t_ref_val="$val" } @@ -287,7 +493,7 @@ t-refs-same () { t-refs-notexist () { local val for g in $*; do - val=`t-git-get-ref $g >$tmp/t.refx` + val=`t-git-get-ref $g` if [ "x$val" != x ]; then fail "ref $g unexpectedly exists ($val)" fi @@ -295,29 +501,50 @@ t-refs-notexist () { } t-v-tag () { - echo refs/tags/debian/${v//\~/_} + echo refs/tags/$tagpfx/${v//\~/_} +} + +t-check-pushed-master () { + local master=`t-git-get-ref refs/heads/master` + if [ x$master = x$t_ref_val ]; then return; fi + if [ x$master = x ]; then fail "failed to push master"; fi + # didn't update master, it must be not FF + local mbase=`t-git-merge-base $master $t_ref_val` + if [ x$mbase = x$master ]; then fail "failed to ff master"; fi } t-pushed-good () { local branch=$1 + local suite=${2:-sid} t-ref-dsc-dgit t-refs-same \ refs/heads/$branch \ `t-v-tag` \ - refs/remotes/dgit/dgit/sid + refs/remotes/dgit/dgit/$suite t-refs-notexist \ refs/heads/dgit/unstable \ refs/remotes/dgit/dgit/unstable - (set -e; cd $tmp/git/$p.git + (set -e; cd $dgitrepo t-refs-same \ - refs/dgit/sid \ + refs/dgit/$suite \ `t-v-tag` + ${t_check_pushed_master:- : NOT-DRS-NO-CHECK-PUSHED-MASTER} t-refs-notexist \ refs/dgit/unstable ) git verify-tag `t-v-tag` } +t-commit-build-push-expect-log () { + local msg=$1 + local mpat=$2 + t-commit "$msg" + t-dgit build + LC_MESSAGES=C \ + t-dgit push --new 2>&1 |tee $tmp/push.log + t-grep-mpat "$mpat" $tmp/push.log +} + t-822-field () { local file=$1 local field=$2 @@ -375,13 +602,59 @@ t-apply-diff () { | patch -p1 -u } +t-gbp-unapplied-pq2qc () { + # does `gbp pq export' + # commits the resulting debian/patches on qc/BRANCH + # leaves us on qc/BRANCH (eg "qc/quilt-tip")) + # qc/BRANCH is not fast-forwarding + + gbp pq export + + branch=`git symbolic-ref HEAD` + branch=${branch#refs/heads/} + + case "$branch" in + */*) fail "unexpected branch $branch" ;; + esac + + git branch -f qc/$branch + git checkout qc/$branch + git add debian/patches + git commit -m 'Commit patch queue' +} + +t-gbp-example-prep () { + t-archive example 1.0-1 + t-git-none + t-worktree 1.0 + + cd example + + t-dgit fetch + + git-checkout -b patch-queue/quilt-tip-2 patch-queue/quilt-tip + gbp pq rebase + + echo '/* some comment */' >>src.c + git add src.c + git commit -m 'Add a comment to an upstream file' + + t-gbp-unapplied-pq2qc + + t-commit 'some updates' 1.0-2 + + git merge -s ours \ + -m 'Pseudo-merge to make descendant of archive' \ + remotes/dgit/dgit/sid +} + t-commit () { local msg=$1 - v=1.$revision - dch -v$v --distribution unstable "$1" + v=${2:-1.$revision} + dch -v$v --distribution ${3:-unstable} "$1" git add debian/changelog debcommit - revision=$(( $revision + 1 )) + revision=$(( ${revision-0} + 1 )) } t-git-config () { @@ -393,20 +666,36 @@ t-drs () { t-git-config dgit-distro.test-dummy.git-url "ext::$troot/drs-git-ext %S " t-git-config dgit-distro.test-dummy.git-check true t-git-config dgit-distro.test-dummy.git-create true - cp $root/tests/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/. - cp $root/tests/suites $tmp/. + t-git-config dgit-distro.test-dummy.dgit-tag-format old,new + cp $troot/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/. + cp $troot/suites $tmp/. + cp $troot/suites $tmp/suites-master + + export t_check_pushed_master=t-check-pushed-master drs_dispatch=$tmp/distro=test-dummy mkdir $drs_dispatch - ln -sf $root $drs_dispatch/dgit-live + + if [ "x$DGIT_TEST_INTREE" != x ]; then + ln -sf "$DGIT_TEST_INTREE" $drs_dispatch/dgit-live + fi + ln -sf $tmp/git $drs_dispatch/repos - ln -sf $tmp/suites $tmp/dm.txt $drs_dispatch/ + ln -sf $tmp/suites $tmp/suites-master $tmp/dm.txt $drs_dispatch/ mkdir -p $drs_dispatch/keyrings ln -sf $tmp/dd.gpg $drs_dispatch/keyrings/debian-keyring.gpg ln -sf $tmp/dm.gpg $drs_dispatch/keyrings/debian-maintainers.gpg ln -sf /bin/true $drs_dispatch/policy-hook } +t-newtag () { + export tagpfx=archive/test-dummy + t-git-config dgit-distro.test-dummy.dgit-tag-format new +} +t-oldtag () { + t-git-config dgit-distro.test-dummy.dgit-tag-format old +} + t-dsd () { t-drs t-git-config dgit-distro.test-dummy.ssh "$troot/dsd-ssh" @@ -428,10 +717,24 @@ t-policy-admin () { ${DGIT_INFRA_PFX}dgit-repos-admin-debian --repos $tmp/git "$@" } +t-policy-nonexist () { + ln -sf no-such-file-or-directory $drs_dispatch/policy-hook +} + +t-make-hook-link () { + local hook=$1 # in infra/ + local linkpath=$2 + hook=${DGIT_INFRA_PFX}$hook + case $hook in + */*) ;; + *) hook=`type -P $hook` ;; + esac + ln -sf "$hook" $linkpath +} + t-policy () { local policyhook=$1 - ln -sf ${DGIT_INFRA_PFX}$policyhook \ - $drs_dispatch/policy-hook + t-make-hook-link $policyhook $drs_dispatch/policy-hook } t-debpolicy () { @@ -447,6 +750,15 @@ t-policy-periodic () { test-dummy $drs_dispatch '' --cron } +t-restrict () { + local restriction=$1 + (cd $root; t-restriction-$restriction >&2) +} + +t-dependencies () { + : "Hopefully installed: $*" +} + t-chain-test () { local ct=$1 local d=${0%/*}