1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Li# Copyright 2007 Google Inc. Released under the GPL v2 3*9c5db199SXin Li# 4*9c5db199SXin Li# Eric Li <[email protected]> 5*9c5db199SXin Li 6*9c5db199SXin Liimport logging, os, pickle, re, sys 7*9c5db199SXin Liimport common 8*9c5db199SXin Li 9*9c5db199SXin Lifrom autotest_lib.client.bin import job as client_job 10*9c5db199SXin Lifrom autotest_lib.client.common_lib import base_job 11*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 12*9c5db199SXin Lifrom autotest_lib.client.common_lib import logging_manager 13*9c5db199SXin Lifrom autotest_lib.client.common_lib import packages 14*9c5db199SXin Li 15*9c5db199SXin Li 16*9c5db199SXin Liclass setup_job(client_job.job): 17*9c5db199SXin Li """ 18*9c5db199SXin Li setup_job is a job which runs client test setup() method at server side. 19*9c5db199SXin Li 20*9c5db199SXin Li This job is used to pre-setup client tests when development toolchain is not 21*9c5db199SXin Li available at client. 22*9c5db199SXin Li """ 23*9c5db199SXin Li 24*9c5db199SXin Li def __init__(self, options): 25*9c5db199SXin Li """ 26*9c5db199SXin Li Since setup_job is a client job but run on a server, it takes no control 27*9c5db199SXin Li file as input. So client_job.__init__ is by-passed. 28*9c5db199SXin Li 29*9c5db199SXin Li @param options: an object passed in from command line OptionParser. 30*9c5db199SXin Li See all options defined on client/bin/autotest. 31*9c5db199SXin Li """ 32*9c5db199SXin Li base_job.base_job.__init__(self, options=options) 33*9c5db199SXin Li self._cleanup_debugdir_files() 34*9c5db199SXin Li self._cleanup_results_dir() 35*9c5db199SXin Li self.machine_dict_list = [{'hostname' : options.hostname}] 36*9c5db199SXin Li # Client side tests should always run the same whether or not they are 37*9c5db199SXin Li # running in the lab. 38*9c5db199SXin Li self.in_lab = False 39*9c5db199SXin Li self.pkgmgr = packages.PackageManager( 40*9c5db199SXin Li self.autodir, run_function_dargs={'timeout':3600}) 41*9c5db199SXin Li 42*9c5db199SXin Li 43*9c5db199SXin Lidef init_test(options, testdir): 44*9c5db199SXin Li """ 45*9c5db199SXin Li Instantiate a client test object from a given test directory. 46*9c5db199SXin Li 47*9c5db199SXin Li @param options Command line options passed in to instantiate a setup_job 48*9c5db199SXin Li which associates with this test. 49*9c5db199SXin Li @param testdir The test directory. 50*9c5db199SXin Li @returns A test object or None if failed to instantiate. 51*9c5db199SXin Li """ 52*9c5db199SXin Li 53*9c5db199SXin Li locals_dict = locals().copy() 54*9c5db199SXin Li globals_dict = globals().copy() 55*9c5db199SXin Li 56*9c5db199SXin Li locals_dict['testdir'] = testdir 57*9c5db199SXin Li 58*9c5db199SXin Li job = setup_job(options=options) 59*9c5db199SXin Li locals_dict['job'] = job 60*9c5db199SXin Li 61*9c5db199SXin Li test_name = os.path.split(testdir)[-1] 62*9c5db199SXin Li outputdir = os.path.join(job.resultdir, test_name) 63*9c5db199SXin Li try: 64*9c5db199SXin Li os.makedirs(outputdir) 65*9c5db199SXin Li except OSError: 66*9c5db199SXin Li pass 67*9c5db199SXin Li locals_dict['outputdir'] = outputdir 68*9c5db199SXin Li 69*9c5db199SXin Li sys.path.insert(0, testdir) 70*9c5db199SXin Li client_test = None 71*9c5db199SXin Li try: 72*9c5db199SXin Li try: 73*9c5db199SXin Li import_stmt = 'import %s' % test_name 74*9c5db199SXin Li init_stmt = ('auto_test = %s.%s(job, testdir, outputdir)' % 75*9c5db199SXin Li (test_name, test_name)) 76*9c5db199SXin Li exec(import_stmt + '\n' + init_stmt, locals_dict, globals_dict) 77*9c5db199SXin Li client_test = globals_dict['auto_test'] 78*9c5db199SXin Li except ImportError as e: 79*9c5db199SXin Li # skips error if test is control file without python test 80*9c5db199SXin Li if re.search(test_name, str(e)): 81*9c5db199SXin Li pass 82*9c5db199SXin Li # give the user a warning if there is an import error. 83*9c5db199SXin Li else: 84*9c5db199SXin Li logging.exception('%s import error: %s. Skipping %s' % 85*9c5db199SXin Li (test_name, e, test_name)) 86*9c5db199SXin Li except Exception as e: 87*9c5db199SXin Li # Log other errors (e.g., syntax errors) and collect the test. 88*9c5db199SXin Li logging.exception("%s: %s", test_name, e) 89*9c5db199SXin Li finally: 90*9c5db199SXin Li sys.path.pop(0) # pop up testbindir 91*9c5db199SXin Li return client_test 92*9c5db199SXin Li 93*9c5db199SXin Li 94*9c5db199SXin Lidef load_all_client_tests(options): 95*9c5db199SXin Li """ 96*9c5db199SXin Li Load and instantiate all client tests. 97*9c5db199SXin Li 98*9c5db199SXin Li This function is inspired from runtest() on client/common_lib/test.py. 99*9c5db199SXin Li 100*9c5db199SXin Li @param options: an object passed in from command line OptionParser. 101*9c5db199SXin Li See all options defined on client/bin/autotest. 102*9c5db199SXin Li 103*9c5db199SXin Li @return a tuple containing the list of all instantiated tests and 104*9c5db199SXin Li a list of tests that failed to instantiate. 105*9c5db199SXin Li """ 106*9c5db199SXin Li 107*9c5db199SXin Li local_namespace = locals().copy() 108*9c5db199SXin Li global_namespace = globals().copy() 109*9c5db199SXin Li 110*9c5db199SXin Li all_tests = [] 111*9c5db199SXin Li broken_tests = [] 112*9c5db199SXin Li for test_base_dir in ['tests', 'site_tests']: 113*9c5db199SXin Li testdir = os.path.join(os.environ['AUTODIR'], test_base_dir) 114*9c5db199SXin Li for test_name in sorted(os.listdir(testdir)): 115*9c5db199SXin Li client_test = init_test(options, os.path.join(testdir, test_name)) 116*9c5db199SXin Li if client_test: 117*9c5db199SXin Li all_tests.append(client_test) 118*9c5db199SXin Li else: 119*9c5db199SXin Li broken_tests.append(test_name) 120*9c5db199SXin Li return all_tests, broken_tests 121*9c5db199SXin Li 122*9c5db199SXin Li 123*9c5db199SXin Lidef setup_test(client_test): 124*9c5db199SXin Li """ 125*9c5db199SXin Li Direct invoke test.setup() method. 126*9c5db199SXin Li 127*9c5db199SXin Li @returns A boolean to represent success or not. 128*9c5db199SXin Li """ 129*9c5db199SXin Li 130*9c5db199SXin Li # TODO: check if its already build. .version? hash? 131*9c5db199SXin Li test_name = client_test.__class__.__name__ 132*9c5db199SXin Li cwd = os.getcwd() 133*9c5db199SXin Li good_setup = False 134*9c5db199SXin Li try: 135*9c5db199SXin Li try: 136*9c5db199SXin Li outputdir = os.path.join(client_test.job.resultdir, test_name) 137*9c5db199SXin Li try: 138*9c5db199SXin Li os.makedirs(outputdir) 139*9c5db199SXin Li os.chdir(outputdir) 140*9c5db199SXin Li except OSError: 141*9c5db199SXin Li pass 142*9c5db199SXin Li logging.info('setup %s.' % test_name) 143*9c5db199SXin Li client_test.setup() 144*9c5db199SXin Li 145*9c5db199SXin Li # Touch .version file under src to prevent further setup on client 146*9c5db199SXin Li # host. See client/common_lib/utils.py update_version() 147*9c5db199SXin Li if os.path.exists(client_test.srcdir): 148*9c5db199SXin Li versionfile = os.path.join(client_test.srcdir, '.version') 149*9c5db199SXin Li pickle.dump(client_test.version, open(versionfile, 'wb')) 150*9c5db199SXin Li good_setup = True 151*9c5db199SXin Li except Exception as err: 152*9c5db199SXin Li logging.error(err) 153*9c5db199SXin Li raise error.AutoservError('Failed to build client test %s on ' 154*9c5db199SXin Li 'server.' % test_name) 155*9c5db199SXin Li finally: 156*9c5db199SXin Li # back to original working dir 157*9c5db199SXin Li os.chdir(cwd) 158*9c5db199SXin Li return good_setup 159*9c5db199SXin Li 160*9c5db199SXin Li 161*9c5db199SXin Lidef setup_tests(options): 162*9c5db199SXin Li """ 163*9c5db199SXin Li Load and instantiate all client tests. 164*9c5db199SXin Li 165*9c5db199SXin Li This function is inspired from runtest() on client/common_lib/test.py. 166*9c5db199SXin Li 167*9c5db199SXin Li @param options: an object passed in from command line OptionParser. 168*9c5db199SXin Li See all options defined on client/bin/autotest. 169*9c5db199SXin Li """ 170*9c5db199SXin Li 171*9c5db199SXin Li assert options.client_test_setup, 'Specify prebuild client tests on the ' \ 172*9c5db199SXin Li 'command line.' 173*9c5db199SXin Li 174*9c5db199SXin Li requested_tests = options.client_test_setup.split(',') 175*9c5db199SXin Li candidates, broken_tests = load_all_client_tests(options) 176*9c5db199SXin Li 177*9c5db199SXin Li failed_tests = [] 178*9c5db199SXin Li if 'all' in requested_tests: 179*9c5db199SXin Li need_to_setup = candidates 180*9c5db199SXin Li failed_tests += broken_tests 181*9c5db199SXin Li else: 182*9c5db199SXin Li need_to_setup = [] 183*9c5db199SXin Li for candidate in candidates: 184*9c5db199SXin Li if candidate.__class__.__name__ in requested_tests: 185*9c5db199SXin Li need_to_setup.append(candidate) 186*9c5db199SXin Li for broken_test in broken_tests: 187*9c5db199SXin Li if broken_test in requested_tests: 188*9c5db199SXin Li failed_tests.append(broken_test) 189*9c5db199SXin Li 190*9c5db199SXin Li if need_to_setup: 191*9c5db199SXin Li cwd = os.getcwd() 192*9c5db199SXin Li os.chdir(need_to_setup[0].job.clientdir) 193*9c5db199SXin Li os.system('tools/make_clean') 194*9c5db199SXin Li os.chdir(cwd) 195*9c5db199SXin Li elif not failed_tests: 196*9c5db199SXin Li logging.error('### No test setup candidates ###') 197*9c5db199SXin Li raise error.AutoservError('No test setup candidates.') 198*9c5db199SXin Li 199*9c5db199SXin Li for client_test in need_to_setup: 200*9c5db199SXin Li good_setup = setup_test(client_test) 201*9c5db199SXin Li if not good_setup: 202*9c5db199SXin Li failed_tests.append(client_test.__class__.__name__) 203*9c5db199SXin Li 204*9c5db199SXin Li logging.info('############################# SUMMARY ' 205*9c5db199SXin Li '#############################') 206*9c5db199SXin Li 207*9c5db199SXin Li # Print out tests that failed 208*9c5db199SXin Li if failed_tests: 209*9c5db199SXin Li logging.info('Finished setup -- The following tests failed') 210*9c5db199SXin Li for failed_test in failed_tests: 211*9c5db199SXin Li logging.info(failed_test) 212*9c5db199SXin Li else: 213*9c5db199SXin Li logging.info('Finished setup -- All tests built successfully') 214*9c5db199SXin Li logging.info('######################### END SUMMARY ' 215*9c5db199SXin Li '##############################') 216*9c5db199SXin Li if failed_tests: 217*9c5db199SXin Li raise error.AutoservError('Finished setup with errors.') 218