diff options
author | Tiancong Wang <tcwang@google.com> | 2020-02-13 21:08:49 +0000 |
---|---|---|
committer | Tiancong Wang <tcwang@google.com> | 2020-02-13 21:08:49 +0000 |
commit | b75f321fc8978b92ce3db6886ccb966768f0c7a8 (patch) | |
tree | 35fa0fbaeaaddd9cc2a126a05eee3527b51e83a8 /deprecated/crb/autotest_run.py | |
parent | cddd960b0ba2eb62c372c0d3176c75f0bd05d5e8 (diff) | |
parent | e617e3393dd24003aa976ece5050bb291070041c (diff) | |
download | toolchain-utils-b75f321fc8978b92ce3db6886ccb966768f0c7a8.tar.gz |
Merging 18 commit(s) from Chromium's toolchain-utils am: 0ae38c8498 am: 2a19d36a82 am: e617e3393dr_aml_301500702android-mainline-12.0.0_r55android-mainline-11.0.0_r9android-mainline-11.0.0_r8android-mainline-11.0.0_r7android-mainline-11.0.0_r6android-mainline-11.0.0_r5android-mainline-11.0.0_r45android-mainline-11.0.0_r44android-mainline-11.0.0_r43android-mainline-11.0.0_r42android-mainline-11.0.0_r41android-mainline-11.0.0_r40android-mainline-11.0.0_r4android-mainline-11.0.0_r39android-mainline-11.0.0_r38android-mainline-11.0.0_r37android-mainline-11.0.0_r36android-mainline-11.0.0_r35android-mainline-11.0.0_r34android-mainline-11.0.0_r33android-mainline-11.0.0_r32android-mainline-11.0.0_r31android-mainline-11.0.0_r30android-mainline-11.0.0_r3android-mainline-11.0.0_r29android-mainline-11.0.0_r28android-mainline-11.0.0_r27android-mainline-11.0.0_r26android-mainline-11.0.0_r25android-mainline-11.0.0_r24android-mainline-11.0.0_r23android-mainline-11.0.0_r22android-mainline-11.0.0_r21android-mainline-11.0.0_r20android-mainline-11.0.0_r2android-mainline-11.0.0_r19android-mainline-11.0.0_r18android-mainline-11.0.0_r17android-mainline-11.0.0_r16android-mainline-11.0.0_r15android-mainline-11.0.0_r14android-mainline-11.0.0_r13android-mainline-11.0.0_r12android-mainline-11.0.0_r10android-mainline-11.0.0_r1android-11.0.0_r48android-11.0.0_r47android-11.0.0_r46android-11.0.0_r45android-11.0.0_r44android-11.0.0_r43android-11.0.0_r42android-11.0.0_r41android-11.0.0_r40android-11.0.0_r39android-11.0.0_r38android-11.0.0_r37android-11.0.0_r36android-11.0.0_r35android-11.0.0_r34android-11.0.0_r33android-11.0.0_r32android-11.0.0_r31android-11.0.0_r30android-11.0.0_r29android-11.0.0_r28android-11.0.0_r27android-11.0.0_r26android-11.0.0_r24android-11.0.0_r23android-11.0.0_r22android-11.0.0_r21android-11.0.0_r20android-11.0.0_r19android-11.0.0_r18android-11.0.0_r16android11-qpr3-s1-releaseandroid11-qpr3-releaseandroid11-qpr2-releaseandroid11-qpr1-s2-releaseandroid11-qpr1-s1-releaseandroid11-qpr1-releaseandroid11-qpr1-d-s1-releaseandroid11-qpr1-d-releaseandroid11-qpr1-c-releaseandroid11-mainline-tethering-releaseandroid11-mainline-sparse-2021-jan-releaseandroid11-mainline-sparse-2020-dec-releaseandroid11-mainline-releaseandroid11-mainline-permission-releaseandroid11-mainline-os-statsd-releaseandroid11-mainline-networkstack-releaseandroid11-mainline-media-swcodec-releaseandroid11-mainline-media-releaseandroid11-mainline-extservices-releaseandroid11-mainline-documentsui-releaseandroid11-mainline-conscrypt-releaseandroid11-mainline-cellbroadcast-releaseandroid11-mainline-captiveportallogin-releaseandroid11-devandroid11-d2-releaseandroid11-d1-b-release
Change-Id: I3f25c7ee034b2e20e37ed941b8eae24eec7043eb
Diffstat (limited to 'deprecated/crb/autotest_run.py')
-rw-r--r-- | deprecated/crb/autotest_run.py | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/deprecated/crb/autotest_run.py b/deprecated/crb/autotest_run.py new file mode 100644 index 00000000..380c578b --- /dev/null +++ b/deprecated/crb/autotest_run.py @@ -0,0 +1,317 @@ +import datetime +import getpass +import glob +import os +import pickle +import re +import threading +import time +import image_chromeos +import machine_manager_singleton +import table_formatter +from cros_utils import command_executer +from cros_utils import logger + +SCRATCH_DIR = '/home/%s/cros_scratch' % getpass.getuser() +PICKLE_FILE = 'pickle.txt' +VERSION = '1' + + +def ConvertToFilename(text): + ret = text + ret = re.sub('/', '__', ret) + ret = re.sub(' ', '_', ret) + ret = re.sub('=', '', ret) + ret = re.sub("\"", '', ret) + return ret + + +class AutotestRun(threading.Thread): + + def __init__(self, + autotest, + chromeos_root='', + chromeos_image='', + board='', + remote='', + iteration=0, + image_checksum='', + exact_remote=False, + rerun=False, + rerun_if_failed=False): + self.autotest = autotest + self.chromeos_root = chromeos_root + self.chromeos_image = chromeos_image + self.board = board + self.remote = remote + self.iteration = iteration + l = logger.GetLogger() + l.LogFatalIf(not image_checksum, "Checksum shouldn't be None") + self.image_checksum = image_checksum + self.results = {} + threading.Thread.__init__(self) + self.terminate = False + self.retval = None + self.status = 'PENDING' + self.run_completed = False + self.exact_remote = exact_remote + self.rerun = rerun + self.rerun_if_failed = rerun_if_failed + self.results_dir = None + self.full_name = None + + @staticmethod + def MeanExcludingSlowest(array): + mean = sum(array) / len(array) + array2 = [] + + for v in array: + if mean != 0 and abs(v - mean) / mean < 0.2: + array2.append(v) + + if array2: + return sum(array2) / len(array2) + else: + return mean + + @staticmethod + def AddComposite(results_dict): + composite_keys = [] + composite_dict = {} + for key in results_dict: + mo = re.match('(.*){\d+}', key) + if mo: + composite_keys.append(mo.group(1)) + for key in results_dict: + for composite_key in composite_keys: + if (key.count(composite_key) != 0 and + table_formatter.IsFloat(results_dict[key])): + if composite_key not in composite_dict: + composite_dict[composite_key] = [] + composite_dict[composite_key].append(float(results_dict[key])) + break + + for composite_key in composite_dict: + v = composite_dict[composite_key] + results_dict['%s[c]' % composite_key] = sum(v) / len(v) + mean_excluding_slowest = AutotestRun.MeanExcludingSlowest(v) + results_dict['%s[ce]' % composite_key] = mean_excluding_slowest + + return results_dict + + def ParseOutput(self): + p = re.compile('^-+.*?^-+', re.DOTALL | re.MULTILINE) + matches = p.findall(self.out) + for i in range(len(matches)): + results = matches[i] + results_dict = {} + for line in results.splitlines()[1:-1]: + mo = re.match('(.*\S)\s+\[\s+(PASSED|FAILED)\s+\]', line) + if mo: + results_dict[mo.group(1)] = mo.group(2) + continue + mo = re.match('(.*\S)\s+(.*)', line) + if mo: + results_dict[mo.group(1)] = mo.group(2) + + # Add a composite keyval for tests like startup. + results_dict = AutotestRun.AddComposite(results_dict) + + self.results = results_dict + + # This causes it to not parse the table again + # Autotest recently added a secondary table + # That reports errors and screws up the final pretty output. + break + mo = re.search('Results placed in (\S+)', self.out) + if mo: + self.results_dir = mo.group(1) + self.full_name = os.path.basename(self.results_dir) + + def GetCacheHashBase(self): + ret = ('%s %s %s' % + (self.image_checksum, self.autotest.name, self.iteration)) + if self.autotest.args: + ret += ' %s' % self.autotest.args + ret += '-%s' % VERSION + return ret + + def GetLabel(self): + ret = '%s %s remote:%s' % (self.chromeos_image, self.autotest.name, + self.remote) + return ret + + def TryToLoadFromCache(self): + base = self.GetCacheHashBase() + if self.exact_remote: + if not self.remote: + return False + cache_dir_glob = '%s_%s' % (ConvertToFilename(base), self.remote) + else: + cache_dir_glob = '%s*' % ConvertToFilename(base) + cache_path_glob = os.path.join(SCRATCH_DIR, cache_dir_glob) + matching_dirs = glob.glob(cache_path_glob) + if matching_dirs: + matching_dir = matching_dirs[0] + cache_file = os.path.join(matching_dir, PICKLE_FILE) + assert os.path.isfile(cache_file) + self._logger.LogOutput('Trying to read from cache file: %s' % cache_file) + return self.ReadFromCache(cache_file) + self._logger.LogOutput('Cache miss. AM going to run: %s for: %s' % + (self.autotest.name, self.chromeos_image)) + return False + + def ReadFromCache(self, cache_file): + with open(cache_file, 'rb') as f: + self.retval = pickle.load(f) + self.out = pickle.load(f) + self.err = pickle.load(f) + self._logger.LogOutput(self.out) + return True + return False + + def StoreToCache(self): + base = self.GetCacheHashBase() + self.cache_dir = os.path.join(SCRATCH_DIR, + '%s_%s' % (ConvertToFilename(base), + self.remote)) + cache_file = os.path.join(self.cache_dir, PICKLE_FILE) + command = 'mkdir -p %s' % os.path.dirname(cache_file) + ret = self._ce.RunCommand(command) + assert ret == 0, "Couldn't create cache dir" + with open(cache_file, 'wb') as f: + pickle.dump(self.retval, f) + pickle.dump(self.out, f) + pickle.dump(self.err, f) + + def run(self): + self._logger = logger.Logger( + os.path.dirname(__file__), '%s.%s' % (os.path.basename(__file__), + self.name), True) + self._ce = command_executer.GetCommandExecuter(self._logger) + self.RunCached() + + def RunCached(self): + self.status = 'WAITING' + cache_hit = False + if not self.rerun: + cache_hit = self.TryToLoadFromCache() + else: + self._logger.LogOutput('--rerun passed. Not using cached results.') + if self.rerun_if_failed and self.retval: + self._logger.LogOutput('--rerun_if_failed passed and existing test ' + 'failed. Rerunning...') + cache_hit = False + if not cache_hit: + # Get machine + while True: + if self.terminate: + return 1 + self.machine = (machine_manager_singleton.MachineManagerSingleton( + ).AcquireMachine(self.image_checksum)) + if self.machine: + self._logger.LogOutput('%s: Machine %s acquired at %s' % + (self.name, self.machine.name, + datetime.datetime.now())) + break + else: + sleep_duration = 10 + time.sleep(sleep_duration) + try: + self.remote = self.machine.name + + if self.machine.checksum != self.image_checksum: + self.retval = self.ImageTo(self.machine.name) + if self.retval: + return self.retval + self.machine.checksum = self.image_checksum + self.machine.image = self.chromeos_image + self.status = 'RUNNING: %s' % self.autotest.name + [self.retval, self.out, self.err] = self.RunTestOn(self.machine.name) + self.run_completed = True + + finally: + self._logger.LogOutput('Releasing machine: %s' % self.machine.name) + machine_manager_singleton.MachineManagerSingleton().ReleaseMachine( + self.machine) + self._logger.LogOutput('Released machine: %s' % self.machine.name) + + self.StoreToCache() + + if not self.retval: + self.status = 'SUCCEEDED' + else: + self.status = 'FAILED' + + self.ParseOutput() + # Copy results directory to the scratch dir + if (not cache_hit and not self.retval and self.autotest.args and + '--profile' in self.autotest.args): + results_dir = os.path.join(self.chromeos_root, 'chroot', + self.results_dir.lstrip('/')) + tarball = os.path.join( + self.cache_dir, os.path.basename(os.path.dirname(self.results_dir))) + command = ('cd %s && tar cjf %s.tbz2 .' % (results_dir, tarball)) + self._ce.RunCommand(command) + perf_data_file = os.path.join(self.results_dir, self.full_name, + 'profiling/iteration.1/perf.data') + + # Attempt to build a perf report and keep it with the results. + command = ('cd %s/src/scripts &&' + ' cros_sdk -- /usr/sbin/perf report --symfs=/build/%s' + ' -i %s --stdio' % (self.chromeos_root, self.board, + perf_data_file)) + ret, out, err = self._ce.RunCommandWOutput(command) + with open(os.path.join(self.cache_dir, 'perf.report'), 'wb') as f: + f.write(out) + return self.retval + + def ImageTo(self, machine_name): + image_args = [image_chromeos.__file__, '--chromeos_root=%s' % + self.chromeos_root, '--image=%s' % self.chromeos_image, + '--remote=%s' % machine_name] + if self.board: + image_args.append('--board=%s' % self.board) + +### devserver_port = 8080 +### mo = re.search("\d+", self.name) +### if mo: +### to_add = int(mo.group(0)) +### assert to_add < 100, "Too many threads launched!" +### devserver_port += to_add + +### # I tried --noupdate_stateful, but that still fails when run in parallel. +### image_args.append("--image_to_live_args=\"--devserver_port=%s" +### " --noupdate_stateful\"" % devserver_port) +### image_args.append("--image_to_live_args=--devserver_port=%s" % +### devserver_port) + +# Currently can't image two machines at once. +# So have to serialized on this lock. + self.status = 'WAITING ON IMAGE_LOCK' + with machine_manager_singleton.MachineManagerSingleton().image_lock: + self.status = 'IMAGING' + retval = self._ce.RunCommand(' '.join(['python'] + image_args)) + machine_manager_singleton.MachineManagerSingleton().num_reimages += 1 + if retval: + self.status = 'ABORTED DUE TO IMAGE FAILURE' + return retval + + def DoPowerdHack(self): + command = 'sudo initctl stop powerd' + self._ce.CrosRunCommand(command, + machine=self.machine.name, + chromeos_root=self.chromeos_root) + + def RunTestOn(self, machine_name): + command = 'cd %s/src/scripts' % self.chromeos_root + options = '' + if self.board: + options += ' --board=%s' % self.board + if self.autotest.args: + options += " --args='%s'" % self.autotest.args + if 'tegra2' in self.board: + self.DoPowerdHack() + command += ('&& cros_sdk -- /usr/bin/test_that %s %s %s' % + (options, machine_name, self.autotest.name)) + return self._ce.RunCommand(command, True) |