218 lines
7.4 KiB
Python
218 lines
7.4 KiB
Python
# Lint as: python2, python3
|
|
# Copyright 2007 Google Inc. Released under the GPL v2
|
|
#
|
|
# Eric Li <ericli@google.com>
|
|
|
|
import logging, os, pickle, re, sys
|
|
import common
|
|
|
|
from autotest_lib.client.bin import job as client_job
|
|
from autotest_lib.client.common_lib import base_job
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.common_lib import logging_manager
|
|
from autotest_lib.client.common_lib import packages
|
|
|
|
|
|
class setup_job(client_job.job):
|
|
"""
|
|
setup_job is a job which runs client test setup() method at server side.
|
|
|
|
This job is used to pre-setup client tests when development toolchain is not
|
|
available at client.
|
|
"""
|
|
|
|
def __init__(self, options):
|
|
"""
|
|
Since setup_job is a client job but run on a server, it takes no control
|
|
file as input. So client_job.__init__ is by-passed.
|
|
|
|
@param options: an object passed in from command line OptionParser.
|
|
See all options defined on client/bin/autotest.
|
|
"""
|
|
base_job.base_job.__init__(self, options=options)
|
|
self._cleanup_debugdir_files()
|
|
self._cleanup_results_dir()
|
|
self.machine_dict_list = [{'hostname' : options.hostname}]
|
|
# Client side tests should always run the same whether or not they are
|
|
# running in the lab.
|
|
self.in_lab = False
|
|
self.pkgmgr = packages.PackageManager(
|
|
self.autodir, run_function_dargs={'timeout':3600})
|
|
|
|
|
|
def init_test(options, testdir):
|
|
"""
|
|
Instantiate a client test object from a given test directory.
|
|
|
|
@param options Command line options passed in to instantiate a setup_job
|
|
which associates with this test.
|
|
@param testdir The test directory.
|
|
@returns A test object or None if failed to instantiate.
|
|
"""
|
|
|
|
locals_dict = locals().copy()
|
|
globals_dict = globals().copy()
|
|
|
|
locals_dict['testdir'] = testdir
|
|
|
|
job = setup_job(options=options)
|
|
locals_dict['job'] = job
|
|
|
|
test_name = os.path.split(testdir)[-1]
|
|
outputdir = os.path.join(job.resultdir, test_name)
|
|
try:
|
|
os.makedirs(outputdir)
|
|
except OSError:
|
|
pass
|
|
locals_dict['outputdir'] = outputdir
|
|
|
|
sys.path.insert(0, testdir)
|
|
client_test = None
|
|
try:
|
|
try:
|
|
import_stmt = 'import %s' % test_name
|
|
init_stmt = ('auto_test = %s.%s(job, testdir, outputdir)' %
|
|
(test_name, test_name))
|
|
exec(import_stmt + '\n' + init_stmt, locals_dict, globals_dict)
|
|
client_test = globals_dict['auto_test']
|
|
except ImportError as e:
|
|
# skips error if test is control file without python test
|
|
if re.search(test_name, str(e)):
|
|
pass
|
|
# give the user a warning if there is an import error.
|
|
else:
|
|
logging.exception('%s import error: %s. Skipping %s' %
|
|
(test_name, e, test_name))
|
|
except Exception as e:
|
|
# Log other errors (e.g., syntax errors) and collect the test.
|
|
logging.exception("%s: %s", test_name, e)
|
|
finally:
|
|
sys.path.pop(0) # pop up testbindir
|
|
return client_test
|
|
|
|
|
|
def load_all_client_tests(options):
|
|
"""
|
|
Load and instantiate all client tests.
|
|
|
|
This function is inspired from runtest() on client/common_lib/test.py.
|
|
|
|
@param options: an object passed in from command line OptionParser.
|
|
See all options defined on client/bin/autotest.
|
|
|
|
@return a tuple containing the list of all instantiated tests and
|
|
a list of tests that failed to instantiate.
|
|
"""
|
|
|
|
local_namespace = locals().copy()
|
|
global_namespace = globals().copy()
|
|
|
|
all_tests = []
|
|
broken_tests = []
|
|
for test_base_dir in ['tests', 'site_tests']:
|
|
testdir = os.path.join(os.environ['AUTODIR'], test_base_dir)
|
|
for test_name in sorted(os.listdir(testdir)):
|
|
client_test = init_test(options, os.path.join(testdir, test_name))
|
|
if client_test:
|
|
all_tests.append(client_test)
|
|
else:
|
|
broken_tests.append(test_name)
|
|
return all_tests, broken_tests
|
|
|
|
|
|
def setup_test(client_test):
|
|
"""
|
|
Direct invoke test.setup() method.
|
|
|
|
@returns A boolean to represent success or not.
|
|
"""
|
|
|
|
# TODO: check if its already build. .version? hash?
|
|
test_name = client_test.__class__.__name__
|
|
cwd = os.getcwd()
|
|
good_setup = False
|
|
try:
|
|
try:
|
|
outputdir = os.path.join(client_test.job.resultdir, test_name)
|
|
try:
|
|
os.makedirs(outputdir)
|
|
os.chdir(outputdir)
|
|
except OSError:
|
|
pass
|
|
logging.info('setup %s.' % test_name)
|
|
client_test.setup()
|
|
|
|
# Touch .version file under src to prevent further setup on client
|
|
# host. See client/common_lib/utils.py update_version()
|
|
if os.path.exists(client_test.srcdir):
|
|
versionfile = os.path.join(client_test.srcdir, '.version')
|
|
pickle.dump(client_test.version, open(versionfile, 'w'))
|
|
good_setup = True
|
|
except Exception as err:
|
|
logging.error(err)
|
|
raise error.AutoservError('Failed to build client test %s on '
|
|
'server.' % test_name)
|
|
finally:
|
|
# back to original working dir
|
|
os.chdir(cwd)
|
|
return good_setup
|
|
|
|
|
|
def setup_tests(options):
|
|
"""
|
|
Load and instantiate all client tests.
|
|
|
|
This function is inspired from runtest() on client/common_lib/test.py.
|
|
|
|
@param options: an object passed in from command line OptionParser.
|
|
See all options defined on client/bin/autotest.
|
|
"""
|
|
|
|
assert options.client_test_setup, 'Specify prebuild client tests on the ' \
|
|
'command line.'
|
|
|
|
requested_tests = options.client_test_setup.split(',')
|
|
candidates, broken_tests = load_all_client_tests(options)
|
|
|
|
failed_tests = []
|
|
if 'all' in requested_tests:
|
|
need_to_setup = candidates
|
|
failed_tests += broken_tests
|
|
else:
|
|
need_to_setup = []
|
|
for candidate in candidates:
|
|
if candidate.__class__.__name__ in requested_tests:
|
|
need_to_setup.append(candidate)
|
|
for broken_test in broken_tests:
|
|
if broken_test in requested_tests:
|
|
failed_tests.append(broken_test)
|
|
|
|
if need_to_setup:
|
|
cwd = os.getcwd()
|
|
os.chdir(need_to_setup[0].job.clientdir)
|
|
os.system('tools/make_clean')
|
|
os.chdir(cwd)
|
|
elif not failed_tests:
|
|
logging.error('### No test setup candidates ###')
|
|
raise error.AutoservError('No test setup candidates.')
|
|
|
|
for client_test in need_to_setup:
|
|
good_setup = setup_test(client_test)
|
|
if not good_setup:
|
|
failed_tests.append(client_test.__class__.__name__)
|
|
|
|
logging.info('############################# SUMMARY '
|
|
'#############################')
|
|
|
|
# Print out tests that failed
|
|
if failed_tests:
|
|
logging.info('Finished setup -- The following tests failed')
|
|
for failed_test in failed_tests:
|
|
logging.info(failed_test)
|
|
else:
|
|
logging.info('Finished setup -- All tests built successfully')
|
|
logging.info('######################### END SUMMARY '
|
|
'##############################')
|
|
if failed_tests:
|
|
raise error.AutoservError('Finished setup with errors.')
|