+autopkgtest (0.7.2~~iwj) unstable; urgency=low
+
+ * adt-run: new --instantiate option to allow package installation to be
+ forced for testing. (This is not an ideal approach - it's not very
+ flexible - but works well enough for the current requirements.)
+ * adt-testreport-onepackage: new ability to test binary as well as
+ source packages, using new --instantiate option.
+ * new `timeout=' option on `execute' virt server command.
+
+ -- Ian Jackson <iwj@ubuntu.com> Fri, 23 Mar 2007 16:58:42 +0000
+
autopkgtest (0.7.2) feisty; urgency=low
* adt-testreport-onepackage: new management script, with some
If this feature is available, execute-debug will
be advertised. Only one such plumbing is available.
+ timeout=<seconds>
+
+ Ensures that the whole execute command does not take
+ more than <seconds>. If it does, the response is
+ timeout
+ instead of `ok <exit-status>'.
+
+ An effort will be made to kill the processes on the
+ testbed but this is not guaranteed to be possible or
+ successful. After an `execute' has timed out, the
+ testbed should probably be reverted with `revert' if
+ that facility is available.
+
* Commands
copydown <host-tree> <testbed-path>
copyup <testbed-tree> <host-path>
help='use binary package DEB according'
' to most recent --binaries-* settings')
+ def cb_actnoarg(op,optstr,value,parser, largsentry):
+ parser.largs.append(largsentry)
+ pa('','--instantiate', action='callback', callback=cb_actnoarg,
+ callback_args=((None, ('instantiate',)),),
+ help='instantiate testbed now (during testing phase)'
+ ' and install packages'
+ ' selected for automatic installation, even'
+ ' if this might apparently not be required otherwise')
+
pa_action('override-control', 'CONTROL', ('control',), is_act=0,
help='run tests from control file CONTROL instead,'
' (applies to next test suite only)')
if kind == 'dsc': fwhatx = '/' + os.path.basename(pathstr)
else: fwhatx = '-'+kind
- af = constructor(what+fwhatx, pathstr, arghandling['tb'])
+ if pathstr is None: af = None
+ else: af = constructor(what+fwhatx, pathstr, arghandling['tb'])
opts.actions.append(Action(kind, af, arghandling, what))
def setup_trace():
binaries = Binaries()
for act in opts.actions:
- if not act.af.spec_tbp:
+ if act.af is not None and not act.af.spec_tbp:
testbed.register_ephemeral(act.af)
binaries.reset()
act.binaries = []
if act.kind.endswith('tree') or act.kind == 'dsc':
control_override = None
+ if act.kind == 'instantiate':
+ pass
debug_a1('builds done.')
debug_a3('run_tests ...')
run_tests(stanzas, act.af)
control_override = None
+ if act.kind == 'instantiate':
+ testbed.prepare([])
debug_a1('tests done.')
def main():
rsync=rsync
disable=true
interactive=true
+target=source
+arch=`dpkg --print-architecture`
for config in "$@"; do
case "$config" in
exit 1
fi
+: ${destdirtail:=$distro-$target}
+: ${destdirfin:="$destdircommon$destdirtail"}
+
+case $target in
+source)
+ sources=Sources
+ descx=''
+ ;;
+binary-*)
+ sources=Packages
+ descx="${target#binary-}"
+ ;;
+*)
+ echo >&2 'target must be source or binary-*'
+ exit 1
+esac
+
exec 3>&1
printf >&3 "starting "
curl -fsS "$1" >"$2"
}
-gurl "$mirror/dists/$distro/$suite/source/Sources.gz" "$tmp"/_sources.gz
-zcat "$tmp"/_sources.gz >"$tmp"/_sources-in
+gurl "$mirror/dists/$distro/$suite/$target/$sources.gz" "$tmp"/_$sources.gz
+zcat "$tmp"/_$sources.gz >"$tmp"/_$sources-in
+
+lastinfo="$var"/lastinfo-$target
now=`date +%s`
->>"$var"/last-info
+>>"$lastinfo"
progress selecting
f2();
f1();
$best_score= -1;
+ sub scorepackage () {
+ return if $skip;
+ return if $score < $best_score
+ or ($score==$best_score and \
+ $package gt $best_package);
+ $best_score= $score;
+ $best_package= $package;
+ }
+ sub endpackage () {
+ return unless (defined $package
+ or defined $version
+ or defined $skip);
+ die unless defined $package;
+ die unless defined $version;
+ scorepackage();
+ undef $package;
+ undef $version;
+ undef $skip;
+ }
while (<F>) {
if (m/^Package: ($pre)$/) {
- die if length $package or length $version;
+ die if defined $package;
$package= $1;
} elsif (m/^Version: ($vre)$/) {
- die unless length $package;
- die if length $version;
+ die if defined $version;
$version= $1;
$score= '$now' - $lasttime{$package};
$score= 1e7 if $score>1e7;
$score *= 5 if $lastver{$package} ne $version;
$score *= 10 unless $extras{$package} =~ m/ nt /;
- next if $score < $best_score
- or ($score==$best_score and \
- $package gt $best_package);
- $best_score= $score;
- $best_package= $package;
+ } elsif (m/^Architecture:.*/ &&
+ !m/\s'$arch'\s/) {
+ $skip= 1;
} elsif (m/^$/) {
- die if length $package and !length $version;
- $package= $version= "";
+ endpackage();
}
}
f2();
+ endpackage();
die unless length $best_package;
open L, ">&4" or die $!;
printf L "selected %s (age %s, score %d)\n",
: "<never-yet>",
$best_score;
print "$best_package\n" or die $!;
- ' "$var"/last-info "$tmp"/_sources-in`"
+ ' "$lastinfo" "$tmp"/_$sources-in`"
else
printf >&4 "package forced: %s\n" "$pkg"
fi
sed -n "/^Package: $pkg\$/,/^\$/p" \
- <"$tmp"/_sources-in >"$tmp"/_this-stanza
+ <"$tmp"/_$sources-in >"$tmp"/_this-stanza
echo
cat "$tmp"/_this-stanza
`"'
}
-getfield Directory
-getfield Version
-
-leafnames="`
- sed -n '/^Files:/,/^([^ ].*)?$/{ /^ /{
- s/^ [0-9a-z][0-9a-z]* *[0-9][0-9]* //; p
- }}' \
- <"$tmp"/_this-stanza
-`"
-
printf >&3 "selected \"%s\" " $pkg
tp="$tmp/$pkg"
mkdir "$tp" "$tp/src" "$tp/tmp" "$tp/out"
-for leafname in $leafnames; do
- df="$tp/src/$leafname"
- case "$leafname" in
- */*|.*) echo >&2 "bad leafname: $leafname"; exit 1;;
- *.dsc) dsc="$df";;
- esac
- gurl "$mirror/$pDirectory/$leafname" "$df"
-done
+getfield Version
+
+if test $target = source; then
+ getfield Directory
+ leafnames="`
+ sed -n '/^Files:/,/^([^ ].*)?$/{ /^ /{
+ s/^ [0-9a-z][0-9a-z]* *[0-9][0-9]* //; p
+ }}' \
+ <"$tmp"/_this-stanza
+ `"
+ for leafname in $leafnames; do
+ df="$tp/src/$leafname"
+ case "$leafname" in
+ */*|.*) echo >&2 "bad leafname: $leafname"; exit 1;;
+ *.dsc) fot="$df";;
+ esac
+ gurl "$mirror/$pDirectory/$leafname" "$df"
+ done
+ testmode=--source
+ testmode2=''
+ desc="$pkg"
+ : ${upload_if_ok:=true}
+else
+ getfield Filename
+ fot="$tp/src/$pkg.deb"
+ gurl "$mirror/$pFilename" "$fot"
+ testmode='--binaries=install --binary'
+ testmode2=--instantiate
+ desc="$pkg $descx"
+ : ${upload_if_ok:=false}
+fi
if [ "x$maintainer_email_override" = x ]; then
getfield Maintainer
--log-file "$tp"/log \
--summary "$tmp"/_summary \
$adtrun_extra_opts \
- --source "$dsc" \
+ $testmode "$fot" $testmode2 \
--- \
adt-virt-xenlvm \
$adtvirt_extra_opts \
extras=''
case "$rc" in
-0) summary='all OK'; email='' ;;
-2) summary='OK (some skipped)'; email='' ;;
+0) summary='all OK'; email=''
+ upload=$upload_if_ok ;;
+2) summary='OK (some skipped)'; email=''
+ upload=$upload_if_ok ;;
8) summary='package declares no tests'; email=''
upload=false; extras='nt' ;;
4|6) summary='test(s) failed!'; email="$maintainer_email" ;;
progress "uploading"
printf >&3 "uploading"
- $rsync -rltH --safe-links --delete "$tp" "$destrsynchead/$destdirtail/"
+ $rsync -rltH --safe-links --delete "$tp" "$destrsynchead/$destdirfin/"
printf >&3 " "
fi
cat >"$tmp"/_email <<END
From: $from
To: $email_addr
-Subject: autopkgtest $distro $pkg: $summary
+Subject: autopkgtest $distro $desc: $summary
- Test executed for: $distro $pkg
+ Test executed for: $distro $target $pkg
Outcome: $summary
END
sed -e 's/^/ /' "$tmp"/_summary >>"$tmp"/_email
failures, can be found below. However, in case this is not
sufficient, another copy can be found along with output files, saved
temporary files, and so on, at:
- $desthttphead/$destdirtail/
+ $desthttphead/$destdirfin/
If you have any questions about this service please contact me at:
$from
END
fi
-printf >>"$var"/log "package=%s rc=%s emailed='%s'\n" \
- "$pkg" $rc "$email_addr"
+printf >>"$var"/log "%s=%s rc=%s emailed='%s'\n" \
+ "$target" "$pkg" $rc "$email_addr"
if [ "x$ourx" = x0 ]; then
- sed -e "/^$pkg /d" <"$var"/last-info >"$var"/last-info.new
+ sed -e "/^$pkg /d" <"$lastinfo" >"$lastinfo".new
printf "%s %s %s %s\n" "$pkg" "$pVersion" "$now" "$extras" \
- >>"$var"/last-info.new
- mv "$var"/last-info.new "$var"/last-info
+ >>"$lastinfo".new
+ mv "$lastinfo".new "$lastinfo"
progress "tested."
else
progress "fault ($ourx)."
disable=false
desthttphead=http://www.chiark.greenend.org.uk/~ijackson/
destrsynchead=ijackson@login.chiark.greenend.org.uk:public-html/
-destdirtail=autopkgtest-output/$distro
+destdircommon=autopkgtest-output/
progname = "<VirtSubproc>"
devnull_read = file('/dev/null','r')
caller = __main__
+copy_timeout = 300
class Quit:
def __init__(q,ec,m): q.ec = ec; q.m = m
+class Timeout: pass
+def alarm_handler(*a): raise Timeout()
+def timeout_start(to): signal.alarm(to)
+def timeout_stop(): signal.alarm(0)
+
+class FailedCmd:
+ def __init__(fc,e): fc.e = e
+
def debug(m):
if not debuglevel: return
print >> sys.stderr, progname+": debug:", m
def preexecfn():
caller.hook_forked_inchild()
-def execute_raw(what, instr, *popenargs, **popenargsk):
+def execute_raw(what, instr, timeout, *popenargs, **popenargsk):
debug(" ++ %s" % string.join(popenargs[0]))
sp = subprocess.Popen(preexec_fn=preexecfn, *popenargs, **popenargsk)
if instr is None: popenargsk['stdin'] = devnull_read
+ timeout_start(timeout)
(out, err) = sp.communicate(instr)
+ timeout_stop()
if err: bomb("%s unexpectedly produced stderr output `%s'" %
(what, err))
status = sp.wait()
return (status, out)
-def execute(cmd_string, cmd_list=[], downp=False, outp=False):
+def execute(cmd_string, cmd_list=[], downp=False, outp=False, timeout=0):
cmdl = cmd_string.split()
if downp: perhaps_down = down
cmd = cmdl + cmd_list
if len(perhaps_down): cmd = perhaps_down + [' '.join(cmd)]
- (status, out) = execute_raw(cmdl[0], None, cmd, stdout=stdout)
+ (status, out) = execute_raw(cmdl[0], None, timeout,
+ cmd, stdout=stdout)
if status: bomb("%s%s failed (exit status %d)" %
((downp and "(down) " or ""), cmdl[0], status))
cmdnumargs(c, ce, 5, None)
debug_re = regexp.compile('debug=(\d+)\-(\d+)$')
debug_g = None
+ timeout = 0
envs = []
for kw in ce[6:]:
if kw.startswith('debug='):
m = debug_re.match(kw)
if not m: bomb("invalid execute debug arg `%s'" % kw)
debug_g = m.groups()
+ elif kw.startswith('timeout='):
+ try: timeout = int(kw[8:],0)
+ except ValueError: bomb("invalid timeout arg `%s'" %kw)
elif kw.startswith('env='):
es = kw[4:]; eq = es.find('=')
if eq <= 0: bomb("invalid env arg `%s'" % kw)
" os._exit(127)\n")
cmdl = down_python_script(gobody)
- (status, out) = execute_raw('sub-python', None, cmdl, stdout=stdout,
- stdin=devnull_read, stderr=subprocess.PIPE)
+ try:
+ (status, out) = execute_raw('sub-python', None, timeout,
+ cmdl, stdout=stdout, stdin=devnull_read,
+ stderr=subprocess.PIPE)
+ except Timeout:
+ raise FailedCmd(['timeout'])
+
if out: bomb("sub-python unexpected produced stdout"
" visible to us `%s'" % out)
return [`status`]
debug(" +> %s" % string.join(cmdls[1]))
subprocs[1] = subprocess.Popen(cmdls[1], stdin=subprocs[0].stdout,
stdout=deststdout, preexec_fn=preexecfn)
+ timeout_start(copy_timeout)
for sdn in [1,0]:
debug(" +"+"<>"[sdn]+"?");
status = subprocs[sdn].wait()
- if status: bomb("%s %s failed, status %d" %
- (wh, ['source','destination'][sdn], status))
+ if status:
+ timeout_stop()
+ bomb("%s %s failed, status %d" %
+ (wh, ['source','destination'][sdn], status))
+ timeout_stop()
def cmd_copydown(c, ce): copyupdown(c, ce, False)
def cmd_copyup(c, ce): copyupdown(c, ce, True)
debug('executing '+string.join(ce))
try: f = globals()['cmd_'+c[0]]
except KeyError: bomb("unknown command `%s'" % ce[0])
- r = f(c, ce)
- if not r: r = []
- r.insert(0, 'ok')
+ try:
+ r = f(c, ce)
+ if not r: r = []
+ r.insert(0, 'ok')
+ except FailedCmd, fc:
+ r = fc.e
print string.join(r)
def cleanup():
sys.exit(16)
def main():
+ signal.signal(signal.SIGALRM, alarm_handler)
debug("down = %s" % string.join(down))
ok()
prepare()