test.py revision 75f161ac96565cb1ae13dd3f7bf0002c003da66f
1# Copyright Martin J. Bligh, Andy Whitcroft, 2006 2# 3# Shell class for a test, inherited by all individual tests 4# 5# Methods: 6# __init__ initialise 7# initialize run once for each job 8# setup run once for each new version of the test installed 9# run run the test (wrapped by job.run_test()) 10# 11# Data: 12# job backreference to the job this test instance is part of 13# outputdir eg. results/<job>/<testname.tag> 14# resultsdir eg. results/<job>/<testname.tag>/results 15# profdir eg. results/<job>/<testname.tag>/profiling 16# debugdir eg. results/<job>/<testname.tag>/debug 17# bindir eg. tests/<test> 18# src eg. tests/<test>/src 19# tmpdir eg. tmp/<testname.tag> 20 21import os, pickle, tempfile, fcntl, traceback 22from autotest_utils import * 23from common.error import * 24import sysinfo 25 26class test: 27 preserve_srcdir = False 28 29 def __init__(self, job, bindir, outputdir): 30 self.job = job 31 self.autodir = job.autodir 32 self.outputdir = outputdir 33 os.mkdir(self.outputdir) 34 self.resultsdir = os.path.join(self.outputdir, 'results') 35 os.mkdir(self.resultsdir) 36 self.profdir = os.path.join(self.outputdir, 'profiling') 37 os.mkdir(self.profdir) 38 self.debugdir = os.path.join(self.outputdir, 'debug') 39 os.mkdir(self.debugdir) 40 41 self.bindir = bindir 42 self.srcdir = os.path.join(self.bindir, 'src') 43 44 tagged_testname = os.path.basename(self.outputdir) 45 self.tmpdir = os.path.join(job.tmpdir, tagged_testname) 46 47 if os.path.exists(self.tmpdir): 48 system('rm -rf ' + self.tmpdir) 49 os.mkdir(self.tmpdir) 50 51 self.job.stdout.tee_redirect( 52 os.path.join(self.debugdir, 'stdout')) 53 self.job.stderr.tee_redirect( 54 os.path.join(self.debugdir, 'stderr')) 55 try: 56 self.initialize() 57 # compile and install the test, if needed. 58 update_version(self.srcdir, self.preserve_srcdir, 59 self.version, self.setup) 60 finally: 61 self.job.stderr.restore() 62 self.job.stdout.restore() 63 64 65 def initialize(self): 66 pass 67 68 69 def setup(self): 70 pass 71 72 73 def cleanup(self): 74 pass 75 76 77 def _exec(self, args, dargs): 78 try: 79 self.job.stdout.tee_redirect( 80 os.path.join(self.debugdir, 'stdout')) 81 self.job.stderr.tee_redirect( 82 os.path.join(self.debugdir, 'stderr')) 83 84 try: 85 os.chdir(self.outputdir) 86 write_keyval(self.outputdir, 87 { 'version' : self.version }) 88 self.execute(*args, **dargs) 89 finally: 90 self.cleanup() 91 self.job.stderr.restore() 92 self.job.stdout.restore() 93 except AutotestError: 94 raise 95 except: 96 raise UnhandledError('running test ' + \ 97 self.__class__.__name__ + "\n") 98 99 100def testname(url): 101 # Extract the testname from the test url. 102 match = re.match('[^:]+://(.*)/([^/]*)$', url) 103 if not match: 104 return ('', url) 105 (group, filename) = match.groups() 106 107 # Generate the group prefix. 108 gfix = re.compile('\W') 109 group = gfix.sub('_', group) 110 111 # Drop the extension to get the raw test name. 112 tfix = re.compile('\.tgz') 113 testname = tfix.sub('', filename) 114 115 return (group, testname) 116 117 118def __installtest(job, url): 119 (group, name) = testname(url) 120 121 ##print "group=%s name=%s" % (group, name) 122 123 # Bail if the test is already installed 124 group_dir = os.path.join(job.testdir, "download", group) 125 if os.path.exists(os.path.join(group_dir, name)): 126 return (group, name) 127 128 # If the group directory is missing create it and add 129 # an empty __init__.py so that sub-directories are 130 # considered for import. 131 if not os.path.exists(group_dir): 132 os.mkdir(group_dir) 133 f = file(os.path.join(group_dir, '__init__.py'), 'w+') 134 f.close() 135 136 print name + ": installing test url=" + url 137 system("wget %s -O %s" % (url, os.path.join(group_dir, 'test.tgz'))) 138 system("cd %s; tar zxf %s" % (group_dir, 'test.tgz')) 139 os.unlink(os.path.join(group_dir, 'test.tgz')) 140 141 # For this 'sub-object' to be importable via the name 142 # 'group.name' we need to provide an __init__.py, 143 # so link the main entry point to this. 144 os.symlink(name + '.py', os.path.join(group_dir, name, 145 '__init__.py')) 146 147 # The test is now installed. 148 return (group, name) 149 150 151# runtest: main interface for importing and instantiating new tests. 152def runtest(job, url, tag, args, dargs): 153 # If this is not a plain test name then download and install 154 # the specified test. 155 if is_url(url): 156 (group, testname) = __installtest(job, url) 157 bindir = os.path.join(job.testdir, "download", group, testname) 158 else: 159 (group, testname) = ('', url) 160 bindir = os.path.join(job.testdir, group, testname) 161 162 outputdir = os.path.join(job.resultdir, testname) 163 164 if (tag): 165 outputdir += '.' + tag 166 if not os.path.exists(bindir): 167 raise TestError(testname + ": test does not exist") 168 169 if group: 170 sys.path.insert(0, os.path.join(job.testdir, "download")) 171 group += '.' 172 else: 173 sys.path.insert(0, os.path.join(job.testdir, testname)) 174 175 try: 176 lockfile = open(os.path.join(job.tmpdir, ".testlock"), "w") 177 fcntl.flock(lockfile, fcntl.LOCK_EX) 178 exec "import %s%s" % (group, testname) 179 exec "mytest = %s%s.%s(job, bindir, outputdir)" % \ 180 (group, testname, testname) 181 finally: 182 fcntl.flock(lockfile, fcntl.LOCK_UN) 183 lockfile.close() 184 sys.path.pop(0) 185 186 pwd = os.getcwd() 187 os.chdir(outputdir) 188 dmesg = os.path.join(mytest.debugdir, 'dmesg') 189 try: 190 mytest._exec(args, dargs) 191 finally: 192 try: 193 # log "after each test" sysinfo 194 sysinfo_dir = os.path.join(mytest.outputdir, 'sysinfo') 195 os.makedirs(sysinfo_dir) 196 try: 197 os.chdir(sysinfo_dir) 198 sysinfo.after_each_test() 199 finally: 200 os.chdir(pwd) 201 202 if os.path.exists(mytest.tmpdir): 203 system('rm -rf ' + mytest.tmpdir) 204 except: 205 print 'post-test error:' 206 traceback.print_exc(file=sys.stdout) 207