blob: 750fc3a27ac3f9079377f1a940b2f47d8756e397 [file] [log] [blame]
mbligh6231cd62008-02-02 19:18:33 +00001# Shell class for a test, inherited by all individual tests
2#
3# Methods:
jadmanski0afbb632008-06-06 21:10:57 +00004# __init__ initialise
5# initialize run once for each job
6# setup run once for each new version of the test installed
7# run run the test (wrapped by job.run_test())
mbligh6231cd62008-02-02 19:18:33 +00008#
9# Data:
jadmanski0afbb632008-06-06 21:10:57 +000010# job backreference to the job this test instance is part of
11# outputdir eg. results/<job>/<testname.tag>
12# resultsdir eg. results/<job>/<testname.tag>/results
13# profdir eg. results/<job>/<testname.tag>/profiling
14# debugdir eg. results/<job>/<testname.tag>/debug
15# bindir eg. tests/<test>
16# src eg. tests/<test>/src
17# tmpdir eg. tmp/<testname.tag>
mbligh6231cd62008-02-02 19:18:33 +000018
jadmanskicc549172008-05-21 18:11:51 +000019import os, sys, re, fcntl, shutil, tarfile, warnings
mbligh6231cd62008-02-02 19:18:33 +000020
jadmanskif55dfc92008-05-16 16:14:54 +000021from autotest_lib.client.common_lib import error, utils
mbligh6231cd62008-02-02 19:18:33 +000022
23
24class base_test:
jadmanski0afbb632008-06-06 21:10:57 +000025 preserve_srcdir = False
mbligh6231cd62008-02-02 19:18:33 +000026
jadmanski0afbb632008-06-06 21:10:57 +000027 def __init__(self, job, bindir, outputdir):
28 self.job = job
29 self.autodir = job.autodir
mbligh6231cd62008-02-02 19:18:33 +000030
jadmanski0afbb632008-06-06 21:10:57 +000031 self.outputdir = outputdir
32 tagged_testname = os.path.basename(self.outputdir)
33 self.resultsdir = os.path.join(self.outputdir, 'results')
34 os.mkdir(self.resultsdir)
35 self.profdir = os.path.join(self.outputdir, 'profiling')
36 os.mkdir(self.profdir)
37 self.debugdir = os.path.join(self.outputdir, 'debug')
38 os.mkdir(self.debugdir)
39 self.bindir = bindir
40 if hasattr(job, 'libdir'):
41 self.libdir = job.libdir
42 self.srcdir = os.path.join(self.bindir, 'src')
mbligh6231cd62008-02-02 19:18:33 +000043
jadmanski0afbb632008-06-06 21:10:57 +000044 self.tmpdir = os.path.join(job.tmpdir, tagged_testname)
mbligh6231cd62008-02-02 19:18:33 +000045
jadmanski0afbb632008-06-06 21:10:57 +000046 if os.path.exists(self.tmpdir):
47 shutil.rmtree(self.tmpdir)
48 os.mkdir(self.tmpdir)
mbligh6231cd62008-02-02 19:18:33 +000049
jadmanski0afbb632008-06-06 21:10:57 +000050 self.job.stdout.tee_redirect(
51 os.path.join(self.debugdir, 'stdout'))
52 self.job.stderr.tee_redirect(
53 os.path.join(self.debugdir, 'stderr'))
54 try:
55 self.initialize()
56 # compile and install the test, if needed.
57 utils.update_version(self.srcdir, self.preserve_srcdir,
58 self.version, self.setup)
59 finally:
60 self.job.stderr.restore()
61 self.job.stdout.restore()
mbligh6231cd62008-02-02 19:18:33 +000062
63
jadmanski0afbb632008-06-06 21:10:57 +000064 def assert_(self, expr, msg='Assertion failed.'):
65 if not expr:
66 raise error.TestError(msg)
mbligh6231cd62008-02-02 19:18:33 +000067
68
jadmanski0afbb632008-06-06 21:10:57 +000069 def write_test_keyval(self, attr_dict):
70 utils.write_keyval(self.outputdir, attr_dict)
jadmanskicc549172008-05-21 18:11:51 +000071
72
jadmanski0afbb632008-06-06 21:10:57 +000073 @staticmethod
74 def _append_type_to_keys(dictionary, typename):
75 new_dict = {}
76 for key, value in dictionary.iteritems():
77 new_key = "%s{%s}" % (key, typename)
78 new_dict[new_key] = value
79 return new_dict
jadmanskicc549172008-05-21 18:11:51 +000080
81
jadmanski0afbb632008-06-06 21:10:57 +000082 def write_iteration_keyval(self, attr_dict, perf_dict):
83 attr_dict = self._append_type_to_keys(attr_dict, "attr")
84 perf_dict = self._append_type_to_keys(perf_dict, "perf")
jadmanskicc549172008-05-21 18:11:51 +000085
jadmanski0afbb632008-06-06 21:10:57 +000086 utils.write_keyval(self.resultsdir, attr_dict,
87 type_tag="attr")
88 utils.write_keyval(self.resultsdir, perf_dict,
89 type_tag="perf")
jadmanskicc549172008-05-21 18:11:51 +000090
jadmanski0afbb632008-06-06 21:10:57 +000091 keyval_path = os.path.join(self.resultsdir, "keyval")
92 print >> open(keyval_path, "a"), ""
jadmanskicc549172008-05-21 18:11:51 +000093
94
jadmanski0afbb632008-06-06 21:10:57 +000095 # TODO: deprecate, remove from code in favour of
96 # the write_*_keyval methods
97 def write_keyval(self, dictionary):
98 warnings.warn("test.write_keyval is deprecated, use "
99 "test.write_test_keyval or "
100 "test.write_iteration_keyval instead",
101 DeprecationWarning)
102 self.write_iteration_keyval({}, dictionary)
mbligh6231cd62008-02-02 19:18:33 +0000103
104
jadmanski0afbb632008-06-06 21:10:57 +0000105 def initialize(self):
106 pass
mbligh6231cd62008-02-02 19:18:33 +0000107
108
jadmanski0afbb632008-06-06 21:10:57 +0000109 def setup(self):
110 pass
mbligh6231cd62008-02-02 19:18:33 +0000111
112
jadmanski0afbb632008-06-06 21:10:57 +0000113 def cleanup(self):
114 pass
mbligh6231cd62008-02-02 19:18:33 +0000115
116
jadmanski0afbb632008-06-06 21:10:57 +0000117 def _exec(self, args, dargs):
118 try:
119 self.job.stdout.tee_redirect(
120 os.path.join(self.debugdir, 'stdout'))
121 self.job.stderr.tee_redirect(
122 os.path.join(self.debugdir, 'stderr'))
mbligh6231cd62008-02-02 19:18:33 +0000123
jadmanski0afbb632008-06-06 21:10:57 +0000124 try:
125 os.chdir(self.outputdir)
126 dargs = dargs.copy()
127 keyvals = dargs.pop('test_attributes', dict())
128 keyvals = keyvals.copy()
129 keyvals['version'] = self.version
130 self.write_test_keyval(keyvals)
mblighd660afe2008-06-05 22:17:53 +0000131
jadmanski0afbb632008-06-06 21:10:57 +0000132 self.execute(*args, **dargs)
133 finally:
134 self.cleanup()
135 self.job.stderr.restore()
136 self.job.stdout.restore()
137 except error.AutotestError:
138 raise
139 except Exception, e:
jadmanski6f731362008-06-17 16:47:06 +0000140 raise error.UnhandledError(e)
mbligh6231cd62008-02-02 19:18:33 +0000141
142
143def testname(url):
jadmanski0afbb632008-06-06 21:10:57 +0000144 # Extract the testname from the test url.
145 match = re.match('[^:]+://(.*)/([^/]*)$', url)
146 if not match:
147 return ('', url)
148 (group, filename) = match.groups()
mbligh6231cd62008-02-02 19:18:33 +0000149
jadmanski0afbb632008-06-06 21:10:57 +0000150 # Generate the group prefix.
151 group = re.sub(r'\W', '_', group)
mbligh6231cd62008-02-02 19:18:33 +0000152
jadmanski0afbb632008-06-06 21:10:57 +0000153 # Drop the extension to get the raw test name.
154 testname = re.sub(r'\.tgz', '', filename)
mbligh6231cd62008-02-02 19:18:33 +0000155
jadmanski0afbb632008-06-06 21:10:57 +0000156 return (group, testname)
mbligh6231cd62008-02-02 19:18:33 +0000157
158
159def _installtest(job, url):
jadmanski0afbb632008-06-06 21:10:57 +0000160 (group, name) = testname(url)
mbligh6231cd62008-02-02 19:18:33 +0000161
jadmanski0afbb632008-06-06 21:10:57 +0000162 # Bail if the test is already installed
163 group_dir = os.path.join(job.testdir, "download", group)
164 if os.path.exists(os.path.join(group_dir, name)):
165 return (group, name)
mbligh6231cd62008-02-02 19:18:33 +0000166
jadmanski0afbb632008-06-06 21:10:57 +0000167 # If the group directory is missing create it and add
168 # an empty __init__.py so that sub-directories are
169 # considered for import.
170 if not os.path.exists(group_dir):
171 os.mkdir(group_dir)
172 f = file(os.path.join(group_dir, '__init__.py'), 'w+')
173 f.close()
mbligh6231cd62008-02-02 19:18:33 +0000174
jadmanski0afbb632008-06-06 21:10:57 +0000175 print name + ": installing test url=" + url
176 get_file(url, os.path.join(group_dir, 'test.tgz'))
177 old_wd = os.getcwd()
178 os.chdir(group_dir)
179 tar = tarfile.open('test.tgz')
180 for member in tar.getmembers():
181 tar.extract(member)
182 tar.close()
183 os.chdir(old_wd)
184 os.remove(os.path.join(group_dir, 'test.tgz'))
mbligh6231cd62008-02-02 19:18:33 +0000185
jadmanski0afbb632008-06-06 21:10:57 +0000186 # For this 'sub-object' to be importable via the name
187 # 'group.name' we need to provide an __init__.py,
188 # so link the main entry point to this.
189 os.symlink(name + '.py', os.path.join(group_dir, name,
190 '__init__.py'))
mbligh6231cd62008-02-02 19:18:33 +0000191
jadmanski0afbb632008-06-06 21:10:57 +0000192 # The test is now installed.
193 return (group, name)
mbligh6231cd62008-02-02 19:18:33 +0000194
195
196def runtest(job, url, tag, args, dargs,
jadmanski0afbb632008-06-06 21:10:57 +0000197 local_namespace={}, global_namespace={}, after_test_hook=None):
198 local_namespace = local_namespace.copy()
199 global_namespace = global_namespace.copy()
mbligh6231cd62008-02-02 19:18:33 +0000200
jadmanski0afbb632008-06-06 21:10:57 +0000201 # if this is not a plain test name then download and install the
202 # specified test
203 if utils.is_url(url):
204 (group, testname) = _installtest(job, url)
205 bindir = os.path.join(job.testdir, 'download', group, testname)
206 site_bindir = None
207 else:
208 # if the test is local, it can be found in either testdir
209 # or site_testdir. tests in site_testdir override tests
210 # defined in testdir
211 (group, testname) = ('', url)
212 bindir = os.path.join(job.testdir, group, testname)
213 if hasattr(job, 'site_testdir'):
214 site_bindir = os.path.join(job.site_testdir,
215 group, testname)
216 else:
217 site_bindir = None
mbligh6231cd62008-02-02 19:18:33 +0000218
jadmanski0afbb632008-06-06 21:10:57 +0000219 outputdir = os.path.join(job.resultdir, testname)
220 if tag:
221 outputdir += '.' + tag
mbligh6231cd62008-02-02 19:18:33 +0000222
jadmanski0afbb632008-06-06 21:10:57 +0000223 # if we can find the test in site_bindir, use this version
224 if site_bindir and os.path.exists(site_bindir):
225 bindir = site_bindir
226 testdir = job.site_testdir
227 elif os.path.exists(bindir):
228 testdir = job.testdir
229 elif not os.path.exists(bindir):
230 raise error.TestError(testname + ': test does not exist')
mbligh6231cd62008-02-02 19:18:33 +0000231
jadmanski0afbb632008-06-06 21:10:57 +0000232 if group:
233 sys.path.insert(0, os.path.join(testdir, 'download'))
234 group += '.'
235 else:
236 sys.path.insert(0, os.path.join(testdir, testname))
mbligh6231cd62008-02-02 19:18:33 +0000237
jadmanski0afbb632008-06-06 21:10:57 +0000238 local_namespace['job'] = job
239 local_namespace['bindir'] = bindir
240 local_namespace['outputdir'] = outputdir
mbligh6231cd62008-02-02 19:18:33 +0000241
jadmanski0afbb632008-06-06 21:10:57 +0000242 lockfile = open(os.path.join(job.tmpdir, '.testlock'), 'w')
243 try:
244 fcntl.flock(lockfile, fcntl.LOCK_EX)
245 exec ("import %s%s" % (group, testname),
246 local_namespace, global_namespace)
247 exec ("mytest = %s%s.%s(job, bindir, outputdir)" %
248 (group, testname, testname),
249 local_namespace, global_namespace)
250 finally:
251 fcntl.flock(lockfile, fcntl.LOCK_UN)
252 lockfile.close()
253 sys.path.pop(0)
mbligh6231cd62008-02-02 19:18:33 +0000254
jadmanski0afbb632008-06-06 21:10:57 +0000255 pwd = os.getcwd()
256 os.chdir(outputdir)
257 try:
258 mytest = global_namespace['mytest']
259 mytest._exec(args, dargs)
260 finally:
261 if after_test_hook:
262 after_test_hook(mytest)