X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=runner%2Fadt-run;h=47036edbc912f9cb8703b79363cfdb2b2d6270c7;hb=0d693f4a2c42db70ba563a2b1100aa2744e23492;hp=4b64ce87f23b1ee194bcf4004a1b7f4a585e6ebd;hpb=3ee21808e5590d4343ddc37b25ba86c825612c8c;p=autopkgtest.git diff --git a/runner/adt-run b/runner/adt-run index 4b64ce8..47036ed 100755 --- a/runner/adt-run +++ b/runner/adt-run @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/python2.6 # # adt-run is part of autopkgtest # autopkgtest is a tool for testing Debian binary packages @@ -40,15 +40,23 @@ import copy from optparse import OptionParser signal.signal(signal.SIGINT, signal.SIG_DFL) # undo stupid Python SIGINT thing +try: our_base = os.environ['AUTOPKGTEST_BASE']+'/lib' +except KeyError: our_base = '/usr/share/autopkgtest/python'; +sys.path.insert(1, our_base) + +from Autopkgtest import * + #---------- global variables -tmpdir = None # pathstring on host +tmp = None # pathstring on host testbed = None # Testbed errorcode = 0 # exit status that we are going to use timeouts = { 'short':100, 'install':3000, 'test':10000, 'build':100000 } binaries = None # Binaries (.debs we have registered) build_essential = ["build-essential"] paths = [] +os.putenv("APT_LISTBUGS_FRONTEND", "none") # do not consider using apt-listbugs +os.putenv("APT_LISTCHANGES_FRONTEND", "none") # do not consider using apt-listchanges #---------- output handling # @@ -255,7 +263,7 @@ class AutoFile: xtra = '' 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))) + raise Exception("internal error: %s (%s)" % (how, str(p))) def _ensure_path(p, tbp): if p.path[tbp] is None: @@ -263,7 +271,7 @@ class AutoFile: p._debug('tmp-parent %s...' % 'HT'[tbp]) TemporaryDir(os.path.dirname(p.what)).write(tbp) if not tbp: - p.path[tbp] = tmpdir+'/'+p.what + p.path[tbp] = tmp+'/'+p.what else: p.ephem[tbp] = True p.path[tbp] = testbed.scratch.path[True]+'/'+p.what @@ -568,8 +576,8 @@ def parse_args(): pa('--set-lang', dest='set_lang', action='store', metavar='LANGVAL', help='set LANG on testbed to LANGVAL', default='C') - pa('','--tmp-dir', type='string', dest='tmpdir', - help='write temporary files to TMPDIR, emptying it' + pa('','--tmp-dir', type='string', dest='tmp', + help='write temporary files to TMP, emptying it' ' beforehand and leaving it behind at the end') pa('','--log-file', type='string', dest='logfile', help='write the log LOGFILE, emptying it beforehand,' @@ -589,7 +597,7 @@ def parse_args(): help='run tests as USER (needs root on testbed)') pa('','--gain-root', type='string', dest='gainroot', help='prefix debian/rules binary with GAINROOT') - pa('-q', '--quiet', action='store_false', dest='quiet', default=False); + pa('-q', '--quiet', action='store_true', dest='quiet', default=False); pa('-d', '--debug', action='count', dest='debuglevel', default=0); pa('','--gnupg-home', type='string', dest='gnupghome', default='~/.autopkgtest/gpg', @@ -638,7 +646,7 @@ def parse_args(): elif type(act) == str: act = (act,act) else: - raise ("unknown action in list `%s' having" + raise Exception("unknown action in list `%s' having" " type `%s'" % (act, type(act))) (pathstr, kindpath) = act @@ -666,21 +674,21 @@ def parse_args(): opts.actions.append(Action(kind, af, arghandling, what)) def setup_trace(): - global trace_stream, tmpdir, summary_stream + global trace_stream, tmp, summary_stream - if opts.tmpdir is not None: - rmtree('tmpdir(specified)',opts.tmpdir) - mkdir_okexist(opts.tmpdir, 0700) - tmpdir = opts.tmpdir + if opts.tmp is not None: + rmtree('tmp(specified)',opts.tmp) + mkdir_okexist(opts.tmp, 0700) + tmp = opts.tmp else: - assert(tmpdir is None) - tmpdir = tempfile.mkdtemp() + assert(tmp is None) + tmp = tempfile.mkdtemp() if opts.logfile is None: if opts.output_dir is not None and opts.output_dir.spec_tbp: opts.logfile = opts.output_dir.spec + '/log' - elif opts.tmpdir is not None: - opts.logfile = opts.tmpdir + '/log' + elif opts.tmp is not None: + opts.logfile = opts.tmp + '/log' if opts.logfile is not None: trace_stream = open(opts.logfile, 'w', 0) if opts.summary is not None: @@ -782,17 +790,12 @@ class Testbed: if len(pec) < 1: tb.bomb('too few results from print-execute-command') cmdl = map(urllib.unquote, pec[0].split(',')) - shellquote_re = regexp.compile('"') - def shellquote_arg(s): return "'" + shellquote_re.sub(r"'\''", s) + "'" - def shellquote_cmdl(l): return ' '.join(map(shellquote_arg,l)) - tb._debug('cmdl = %s' % (`cmdl`)) tb.ec_auxverbscript = TemporaryFile('satdep-auxverb') print >>open(tb.ec_auxverbscript.write(),'w'), ( '''#!/bin/sh -set -ex -echo >&2 ": $*" +set -e if [ $# = 2 ] && [ "x$1" = xdpkg-architecture ] && [ "x$2" = x-qDEB_HOST_ARCH ]; then # This is a pretty nasty hack. Hopefully it can go away # eventually. See #635763. @@ -813,6 +816,14 @@ exec '''+shellquote_cmdl(cmdl)+' "$@"'+"\n" if rc: pstderr("\n" "warning: failed to restore" " testbed apt cache, exit code %d" % rc) + what = 'aptconf-reset' + cmdl = ['rm','-f','/etc/apt/apt.conf.d/90autopkgtest', + '/etc/apt/sources.list.d/autopkgtest.list', + '/etc/apt/preferences.d/90autopkgtest'] + rc = tb.execute(what, cmdl, kind='install') + if rc: + pstderr("\n" "warning: failed to reset changes" + " made to testbed apt configuration, exit code %d" % rc) tb._need_reset_apt = False def close(tb): tb._debug('close, scratch=%s' % tb.scratch) @@ -907,7 +918,7 @@ exec '''+shellquote_cmdl(cmdl)+' "$@"'+"\n" return rl[0] def execute(tb, what, cmdl, si='/dev/null', so='/dev/null', se=None, cwd=None, - script=False, tmpdir=None, kind='short'): + script=False, xenv=[], kind='short'): # Options for script: # False - do not call debug_subprocess, no synch. reporting required # None or string - call debug_subprocess with that value, @@ -942,7 +953,7 @@ exec '''+shellquote_cmdl(cmdl)+' "$@"'+"\n" cmdl.append('timeout=%d' % timeout) if xdump is not None and 'execute-debug' in tb.caps: cmdl += [xdump] - if tmpdir is not None: cmdl.append('env=TMPDIR=%s' % tmpdir) + for e in xenv: cmdl.append('env=%s' % e) if kind=='install': cmdl.append('env=DEBIAN_FRONTEND=noninteractive') if opts.set_lang is not False: cmdl.append('env=LANG=%s' % opts.set_lang) @@ -1012,15 +1023,16 @@ class Restriction: def __init__(r,rname,base): pass class Restriction_rw_build_tree(Restriction): pass +class Restriction_build_needed(Restriction): pass class Restriction_breaks_testbed(Restriction): def __init__(r, rname, base): - if 'revert' not in testbed.caps: - raise Unsupported(f.lno, - 'Test breaks testbed but testbed cannot revert') + if 'revert-full-system' not in testbed.caps: + raise Unsupported(-1, + 'Test breaks testbed but testbed does not advertise revert-full-system') class Restriction_needs_root(Restriction): def __init__(r, rname, base): if 'root-on-testbed' not in testbed.caps: - raise Unsupported(f.lno, + raise Unsupported(-1, 'Test needs root on testbed which is not available') class Field_Restrictions(FieldBase): @@ -1050,7 +1062,7 @@ class Field_Tests(FieldIgnore): pass class Field_Depends(FieldBase): def parse(f): - print >>sys.stderr, "Field_Depends:", `f.stz`, `f.base`, `f.tnames`, `f.vl` + debug("Field_DependS: %s %s %s %s" % (f.stz, f.base, f.tnames, f.vl), 2) dl = map(lambda x: x.strip(), flatten(map(lambda (lno, v): v.split(','), f.vl))) re = regexp.compile('[^-.+:~0-9a-z()<>=*@]') @@ -1114,9 +1126,9 @@ class Test: dn.append(d) else: for (pkg,bin) in t.act.binaries: - d = d.replace('@',pkg) - t._debug(' synthesised dependency '+d) - dn.append(d) + dp = d.replace('@',pkg) + t._debug(' synthesised dependency '+dp) + dn.append(dp) testbed.prepare(dn) def run(t, tree): t._debug('[----------------------------------------') @@ -1136,29 +1148,30 @@ class Test: se = stdouterr('stderr') tf = af.read(True) - tmpdir = None + xenv = [] rc = testbed.execute('testchmod-'+t.what, ['chmod','+x','--',tf]) if rc: bomb('failed to chmod +x %s' % tf) 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) + testtmp = '%s%s-testtmp' % (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 + xenv.append('TMPDIR=%s' % testtmp) rc = testbed.execute('mktmpdir-'+t.what, - ['sh','-xec',script,'x',tmpdir,tree.read(True)]) - if rc: bomb("could not create test tmpdir `%s', exit code %d" - % (tmpdir, rc)) + ['sh','-xec',script,'x',xenv=xenv,tree.read(True)]) + if rc: bomb("could not create test tmp `%s', exit code %d" + % (testtmp, rc)) else: tfl = [tf] rc = testbed.execute('test-'+t.what, tfl, so=so.write(True), se=se.write(True), cwd=tree.read(True), - tmpdir=tmpdir, kind='test') + xenv=xenv, kind='test') so_read = so.read() se_read = se.read() @@ -1202,19 +1215,22 @@ def read_control(act, tree, control_override): return [] lno = 0 - def badctrl(m): act.bomb('tests/control line %d: %s' % (lno, m)) - stz = None # stz[field_name][index] = (lno, value) + def badctrl(m): testbed.bomb('tests/control line %d: %s' % (lno, m)) + stz = { } # stz[field_name][index] = (lno, value) # special field names: # stz[' lno'] = number # stz[' tests'] = list of Test objects + # empty dictionary means we're between stanzas + def in_stanza(stz): + return stz.has_key(' lno') def end_stanza(stz): - if stz is None: return + if not in_stanza(stz): return stz[' errs'] = 0 - stanzas.append(stz) - stz = None + stanzas.append(stz.copy()) + stz.clear() hcurrent = None - initre = regexp.compile('([A-Z][-0-9a-z]*)\s*\:\s*(.*)$') + initre = regexp.compile('([A-Z][-0-9a-zA-Z]*)\s*\:\s*(.*)$') while 1: l = control.readline() if not l: break @@ -1226,7 +1242,7 @@ def read_control(act, tree, control_override): if initmat: (fname, l) = initmat.groups() fname = string.capwords(fname) - if stz is None: + if not in_stanza(stz): stz = { ' lno': lno, ' tests': [] } if not stz.has_key(fname): stz[fname] = [ ] hcurrent = stz[fname] @@ -1297,8 +1313,8 @@ def cleanup(): if testbed is not None: testbed.reset_apt() testbed.stop() - if opts.tmpdir is None and tmpdir is not None: - rmtree('tmpdir', tmpdir) + if opts.tmp is None and tmp is not None: + rmtree('tmp', tmp) if trace_stream is not None: trace_stream.close() trace_stream = None @@ -1329,7 +1345,7 @@ class Binaries: ok = False if opts.gnupghome is None: - opts.gnupghome = tmpdir+'/gnupg' + opts.gnupghome = tmp+'/gnupg' b._debug('initialising') try: @@ -1663,12 +1679,8 @@ def build_source(act, control_override): stanzas = read_control(act, result_pwd_af, control_override) for stanza in stanzas: for t in stanza[' tests']: - if 'no-build-needed' not in t.feature_names: + if 'build-needed' in t.restriction_names: build_needed('test %s' % t.tname) - for d in t.depends: - if '@' in d: - build_needed('test %s ' - 'dependency %s' % (t.tname,d)) debug_b('build not needed') built = False @@ -1819,7 +1831,7 @@ def process_actions(): def main(): global testbed - global tmpdir + global tmp try: parse_args() except SystemExit, se: