testbed = None # Testbed
errorcode = 0 # exit status that we are going to use
binaries = None # Binaries (.debs we have registered)
+build_essential = ["build-essential"]
#---------- output handling
#
# is done by forking off a copy of ourselves to do plumbing,
# which copy we wait for at the appropriate point.
+class DummyOpts:
+ def __init__(do): do.debuglevel = 0
+
+opts = DummyOpts()
trace_stream = None
+summary_stream = None
def pstderr(m):
print >>sys.stderr, m
else: ep.stream = trace_stream
ep._sp = None
else:
- ep._sp = subprocess.Popen(['tee','/dev/stderr'],
+ ep._sp = subprocess.Popen(['tee','-a','/dev/stderr'],
stdin=subprocess.PIPE, stdout=trace_stream,
close_fds=True)
ep.stream = ep._sp.stdin
ep.wait()
return (rc, output)
+def psummary(m):
+ if summary_stream is not None: print >>summary_stream, m
+
def preport(m):
print m
+ sys.stdout.flush()
if trace_stream is not None: print >>trace_stream, m
+ psummary(m)
def report(tname, result):
preport('%-20s %s' % (tname, result))
else: return p.path[tbp]+p.dir+'!'
out = p.what
if p.spec is not None:
- if p.spec_tbp: out += '#'
+ if not hasattr(p,'spec_tb'): out += '~'
+ elif p.spec_tbp: out += '#'
else: out += '='
out += p.spec
out += ':'
def _wrong(p, how):
xtra = ''
- if p.spec is not None: xtra = ' spec[%s]=%s' % (p.spec, p.spec_tb)
+ if p.spec is not None:
+ xtra = ' spec[%s]=%s' % (p.spec, getattr(p,'spec_tb',None))
raise ("internal error: %s (%s)" % (how, str(p)))
def _ensure_path(p, tbp):
def parse_args():
global opts
+ global n_non_actions # argh, stupid python scoping rules
usage = "%prog <options> --- <virt-server>..."
parser = OptionParser(usage=usage)
pa = parser.add_option
# actions (ie, test sets to run, sources to build, binaries to use):
def cb_action(op,optstr,value,parser, long,kindpath,is_act):
+ global n_non_actions
parser.largs.append((value,kindpath))
n_non_actions += not(is_act)
def cb_path(op,optstr,value,parser, constructor,long,dir):
name = long.replace('-','_')
- af = constructor(arghandling['tb'], value, long, dir)
+ af = constructor(long, value,arghandling['tb'])
setattr(parser.values, name, af)
def pa_path(long, constructor, help, dir=False):
pa('','--log-file', type='string', dest='logfile',
help='write the log LOGFILE, emptying it beforehand,'
' instead of using OUTPUT-DIR/log or TMPDIR/log')
+ pa('','--summary-file', type='string', dest='summary',
+ help='write a summary report to SUMMARY,'
+ ' emptying it beforehand')
pa('','--user', type='string', dest='user',
help='run tests as USER (needs root on testbed)')
opts.actions.append(Action(kind, af, arghandling, what))
def setup_trace():
- global trace_stream, tmpdir
+ global trace_stream, tmpdir, summary_stream
if opts.tmpdir is not None:
rmtree('tmpdir(specified)',opts.tmpdir)
opts.logfile = opts.tmpdir + '/log'
if opts.logfile is not None:
trace_stream = open(opts.logfile, 'w', 0)
+ if opts.summary is not None:
+ summary_stream = open(opts.summary, 'w', 0)
debug('options: '+`opts`, 1)
def finalise_options():
- global opts, tb
+ global opts, tb, build_essential
if opts.user is None and 'root-on-testbed' not in testbed.caps:
opts.user = ''
if (opts.user or
'root-on-testbed' not in testbed.caps):
opts.gainroot = 'fakeroot'
+ build_essential += ['fakeroot']
if opts.gnupghome.startswith('~/'):
try: home = os.environ['HOME']
(tb.modified, tb.deps_processed, deps_new), 1)
if 'revert' in tb.caps and (tb.modified or
[d for d in tb.deps_processed if d not in deps_new]):
+ for af in tb._ephemeral: af.read(False)
tb._debug('reset **')
tb.command('revert')
tb.blamed = []
tb.prepare1(deps_new)
tb.prepare2(deps_new)
def register_ephemeral(tb, af):
- if not getattr(af,'spec_tbp',False): tb._ephemeral.append(af)
+ tb._ephemeral.append(af)
def _install_deps(tb, deps_new):
tb._debug(' installing dependencies '+`deps_new`, 1)
tb.deps_processed = deps_new
global errorcode, testbed
if stanzas == ():
report('*', 'SKIP no tests in this package')
+ errorcode |= 8
for stanza in stanzas:
tests = stanza[' tests']
if not tests:
for t in tests:
t.prepare()
t.run(tree)
- if 'breaks-testbed' in t.restrictions:
+ if 'breaks-testbed' in t.restriction_names:
testbed.needs_reset()
testbed.needs_reset()
t._debug('[----------------------------------------')
def stdouterr(oe):
idstr = t.what + '-' + oe
- if opts.output_dir is not None and opts.output_dir.tb:
+ if opts.output_dir is not None and opts.output_dir.spec_tbp:
use_dir = opts.output_dir
else:
use_dir = testbed.scratch
tf = af.read(True)
tmpdir = None
+ tree.read(True)
+
+ rc = testbed.execute('testchmod-'+t.what, ['chmod','+x','--',tf])
+ if rc: bomb('failed to chmod +x %s' % tf)
- if 'needs-root' not in t.restrictions:
- tf = opts.user_wrap(tf)
- tmpdir = '%s/%s-tmpdir' % (testbed.scratch.read(True), t.what)
+ if 'needs-root' not in t.restriction_names and opts.user is not None:
+ tfl = ['su',opts.user,'-c',tf]
+ tmpdir = '%s%s-tmpdir' % (testbed.scratch.read(True), t.what)
script = 'rm -rf -- "$1"; mkdir -- "$1"'
if opts.user: script += '; chown %s "$1"' % opts.user
+ if 'rw-build-tree' in t.restriction_names:
+ script += '; chown -R %s "$2"' % opts.user
rc = testbed.execute('mktmpdir-'+t.what,
- ['sh','-xec',script,'x',tmpdir])
+ ['sh','-xec',script,'x',tmpdir,tree.read(True)])
if rc: bomb("could not create test tmpdir `%s', exit code %d"
% (tmpdir, rc))
+ else:
+ tfl = [tf]
- rc = testbed.execute('test-'+t.what, [tf],
+ rc = testbed.execute('test-'+t.what, tfl,
so=so.write(True), se=se.write(True), cwd=tree.read(True),
tmpdir=tmpdir)
if stab.st_size != 0:
l = open(se_read).readline()
l = l.rstrip('\n \t\r')
- if len(l) > 40: l = l[:40] + '...'
+ if len(l) > 35: l = l[:35] + '...'
t.reportfail('status: %d, stderr: %s' % (rc, l))
t._debug(' - - - - - - - - - - stderr - - - - - - - - - -')
debug_file(se_read)
(et, q, tb) = ei
if et is Quit:
pstderr('adt-run: ' + q.m)
+ psummary('quitting: '+q.m)
return q.ec
else:
pstderr("adt-run: unexpected, exceptional, error:")
+ psummary('quitting: unexpected error, consult transcript')
traceback.print_exc(None, sys.stderr)
if trace_stream is not None:
traceback.print_exc(None, trace_stream)
'print res',
'print d.missingDeps',
'print d.requiredChanges',
- 'assert(res)',
+ 'if not res: raise "gdebi failed (%s, %s, %s): %s" % '+
+ ' (`res`, `d.missingDeps`, `d.requiredChanges`, '+
+ 'd._failureString)',
'cache.commit()',
''
]
results = open(so.read()).read().rstrip('\n')
if len(results): results = results.split("\n")
else: results = []
- if rc: badpkg("%s failed with exit code %d" % (which,rc))
+ if rc: badpkg("rules %s failed with exit code %d" % (which,rc))
if results_lines is not None and len(results) != results_lines:
badpkg("got %d lines of results from %s where %d expected"
% (len(results), which, results_lines))
script = binaries.apt_pkg_gdebi_script('', [[
'from GDebi.DebPackage import DebPackage',
'd = DebPackage(cache)',
- 'res = d.satisfyDependsStr("dpkg-source")',
+ 'res = d.satisfyDependsStr("dpkg-dev")',
]])
cmdl = ['python','-c',script]
whatp = what+'-dpkgsource'
for stanza in stanzas:
for t in stanza[' tests']:
if 'no-build-needed' not in t.feature_names:
- build_needed('test %s' % t.name)
+ build_needed('test %s' % t.tname)
for d in t.depends:
if '@' in d:
build_needed('test %s '
- 'dependency %s' % (t.name,d))
+ 'dependency %s' % (t.tname,d))
debug_b('build not needed')
built = False
],[
'from GDebi.DebPackage import DebPackage',
'd = DebPackage(cache)',
- 'res = d.satisfyDependsStr("build-essential")',
+ 'res = d.satisfyDependsStr("'+
+ ','.join(build_essential)+
+ '")',
]])
cmdl = ['python','-c',script]
work.read(True)+os.path.basename(result_pwd),
True)
if act.ah['dsc_tests']:
- act.tests_tree.read()
testbed.register_ephemeral(act.work)
testbed.register_ephemeral(act.tests_tree)
- if not built: return
+ if not built:
+ act.blamed = []
+ return
act.blamed = copy.copy(testbed.blamed)
binaries = Binaries()
for act in opts.actions:
- testbed.register_ephemeral(act.af)
+ if not act.af.spec_tbp:
+ testbed.register_ephemeral(act.af)
binaries.reset()
control_override = None
from="$salutation Jackson <ian@davenant.greenend.org.uk>"
rsync=rsync
disable=true
+interactive=true
for config in "$@"; do
- . "$config"
+ case "$config" in
+ *=*) eval "$config" ;;
+ *) . "$config" ;;
+ esac
done
if $disable; then
exit 1
fi
-destdirtail=autopkgtest-output/$distro
-destrsynchead=ijackson@chiark:public-html/
-desthttphead=http://www.chiark.greenend.org.uk/~ijackson/
+exec 3>&1
+printf >&3 "starting "
rm -rf "$tmp"
mkdir "$tmp"
-exec >"$tmp"/log 5>&1
+>"$tmp"/_log
+
+if $interactive; then
+ echo '(log diverted to stdout)' >>"$tmp"/_log
+else
+ exec >>"$tmp"/_log
+fi
+exec 4>&1
progress () {
echo "++++++ $1 ++++++"
gurl () {
progress "fetching $1"
- curl -sS "$1" >"$2"
+ 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/source/Sources.gz" "$tmp"/_sources.gz
+zcat "$tmp"/_sources.gz >"$tmp"/_sources-in
now=`date +%s`
>>"$var"/last-info
progress selecting
-pkg="`perl -e '
+if [ "x$pkg" = x ]; then
+ pkg="`perl -e '
use IO::Handle;
$pre= "[-+.0-9a-z]+";
f1();
while (<F>) {
- die unless m/^($pre) ($vre) (\d+)$/;
+ die unless m/^($pre) ($vre) (\d+)( .*)?$/;
$lastver{$1}= $2;
$lasttime{$1}= $3;
+ $extras{$1}= $4." ";
}
f2();
f1();
die if length $version;
$version= $1;
$score= '$now' - $lasttime{$package};
- $score= 1e8 if $score>1e8;
+ $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);
}
f2();
die unless length $best_package;
- open L, ">&5" or die $!;
+ open L, ">&4" or die $!;
printf L "selected %s (age %s, score %d)\n",
$best_package,
exists($lastime{$best_package})
: "<never-yet>",
$best_score;
print "$best_package\n" or die $!;
-' "$var"/last-info "$tmp"/sources-in`"
+ ' "$var"/last-info "$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
+cat "$tmp"/_this-stanza
getfield () {
eval 'p'$1'="`
sed -n '\''s/^'$1': //p'\'' \
- <"$tmp"/this-stanza
+ <"$tmp"/_this-stanza
`"'
}
sed -n '/^Files:/,/^([^ ].*)?$/{ /^ /{
s/^ [0-9a-z][0-9a-z]* *[0-9][0-9]* //; p
}}' \
- <"$tmp"/this-stanza
+ <"$tmp"/_this-stanza
`"
+printf >&3 "selected \"%s\" " $pkg
+
tp="$tmp/$pkg"
mkdir "$tp" "$tp/src" "$tp/tmp" "$tp/out"
*/*|.*) echo >&2 "bad leafname: $leafname"; exit 1;;
*.dsc) dsc="$df";;
esac
- gurl "$mirror/pool/$suite/$pDirectory/$leafname" "$df"
+ gurl "$mirror/$pDirectory/$leafname" "$df"
done
if [ "x$maintainer_email_override" = x ]; then
maintainer_email=maintainer_email_override
fi
+printf >&3 "adt-run "
+
progress "starting test"
xrc () {
set -e
}
+echo 'fatal: adt-run did not start properly' >"$tmp"/_summary
+
xrc adt-run --tmp-dir "$tp"/tmp \
--output-dir "$tp"/out \
--log-file "$tp"/log \
+ --summary "$tmp"/_summary \
+ $adtrun_extra_opts \
--source "$dsc" \
--- \
adt-virt-xenlvm \
- distro="$distro" \
- 2>&1
+ $adtvirt_extra_opts \
+ -- \
+ --distro="$distro" \
+ 2>&1 3>&- 4>&-
+
+printf >&3 "%s " $rc
+
+ourx=0
+upload=true
+extras=''
case "$rc" in
0) summary='all OK'; email='' ;;
2) summary='OK (some skipped)'; email='' ;;
-8) summary='package declares no tests'; email='' ;;
+8) summary='package declares no tests'; email=''
+ upload=false; extras='nt' ;;
4|6) summary='test(s) failed!'; email="$maintainer_email" ;;
12) summary='erroneous package!'; email="$maintainer_email" ;;
16) summary='testbed failed!'; email="administrator_email" ;;
-*) summary='unexpected failure!'; email="administrator_email" ;;
+*) summary='unexpected failure!'; email="administrator_email"; ourx=20;;
esac
progress "RESULTS $summary"
-progress "contacting $email"
-for odir in tmp out; do
- if test -d "$tp"/$odir; then
- GZIP=-2 tar -f "$tp"/$odir.tar.gz -C "$tp" -zc $odir
- rm -r "$tp"/$odir
- fi
-done
-
-$rsync -rltH --safe-links --delete "$tp" "$destrsynchead/$destdirtail/"
+if $upload; then
+ progress "bundling"
+ ln "$tmp"/_summary "$tp"/summary
+
+ for odir in tmp out; do
+ if test -d "$tp"/$odir; then
+ GZIP=-2 tar -f "$tp"/$odir.tar.gz -C "$tp" -zc $odir
+ rm -r "$tp"/$odir
+ fi
+ done
+
+ progress "uploading"
+ printf >&3 "uploading"
+ $rsync -rltH --safe-links --delete "$tp" "$destrsynchead/$destdirtail/"
+ printf >&3 " "
+fi
if [ "x$email" != x ]; then
+ progress "contacting $email"
eval "email_addr=\$$email"
- cat >"$tmp"/email <<END
+ printf >&3 "email \"%s\" " "$email_addr"
+ cat >"$tmp"/_email <<END
From: $from
To: $email_addr
Subject: autopkgtest $distro $pkg: $summary
Test executed for: $distro $pkg
Outcome: $summary
+END
+ sed -e 's/^/ /' "$tmp"/_summary >>"$tmp"/_email
+ cat >>"$tmp"/_email <<END
This message is automatically generated by the autopkgtest package
testing system. You are receiving it because:
END
case "$email" in
pMaintainer)
- cat >>"$tmp"/email <<END
+ cat >>"$tmp"/_email <<END
You are listed in the Maintainer field of the $pkg package in $distro
and the test results appear to indicate a problem with the package.
END
;;
maintainer_email_override)
- cat >>"$tmp"/email <<END
+ cat >>"$tmp"/_email <<END
The test results appear to indicate a problem with the package
and reports for package maintainers for $distro are being directed to
$maintainer_email_override
END
;;
administrator_email)
- cat >>"$tmp"/email <<END
+ cat >>"$tmp"/_email <<END
You are the administrator for the autopkgtest installation.
END
;;
exit 1
;;
esac
- cat >>"$tmp/email" <<END
+ cat >>"$tmp/_email" <<END
The test log, which is intended to be sufficient to diagnose most
failures, can be found below. However, in case this is not
-8<-
END
- cat >>"$tmp"/email 2>&1 "$tmp"/log ||:
- sendmail -odq -oem -t -oi <"$tmp"/email
fi
printf >>"$var"/log "package=%s rc=%s emailed='%s'\n" \
"$pkg" $rc "$email_addr"
-sed -e "/^$pkg /d" <"$var"/last-info >"$var"/last-info.new
-printf "%s %s %s\n" "$pkg" "$pVersion" "$now" >>"$var"/last-info.new
-mv "$var"/last-info.new "$var"/last-info
+if [ "x$ourx" = x0 ]; then
+ sed -e "/^$pkg /d" <"$var"/last-info >"$var"/last-info.new
+ printf "%s %s %s %s\n" "$pkg" "$pVersion" "$now" "$extras" \
+ >>"$var"/last-info.new
+ mv "$var"/last-info.new "$var"/last-info
+ progress "tested."
+else
+ progress "fault ($ourx)."
+fi
+
+if [ "x$email" = x ]; then
+ if $interactive; then
+ cat "$tmp"/_log >&2
+ fi
+else
+ cat >>"$tmp"/_email 2>&1 "$tmp"/_log ||:
+ if $interactive; then
+ cat "$tmp"/_email >&2
+ else
+ sendmail -odq -oem -t -oi <"$tmp"/_email
+ fi
+fi
-progress "done."
+printf >&3 "done %s.\n" $ourx
+exit $ourx