aboutsummaryrefslogtreecommitdiff
path: root/deprecated/crb
diff options
context:
space:
mode:
Diffstat (limited to 'deprecated/crb')
-rw-r--r--deprecated/crb/autotest_gatherer.py67
-rw-r--r--deprecated/crb/autotest_run.py317
-rwxr-xr-xdeprecated/crb/crb_driver.py370
-rw-r--r--deprecated/crb/machine_manager_singleton.py153
-rw-r--r--deprecated/crb/table_formatter.py258
5 files changed, 1165 insertions, 0 deletions
diff --git a/deprecated/crb/autotest_gatherer.py b/deprecated/crb/autotest_gatherer.py
new file mode 100644
index 00000000..f8f7b43f
--- /dev/null
+++ b/deprecated/crb/autotest_gatherer.py
@@ -0,0 +1,67 @@
+from table_formatter import TableFormatter as TableFormatter
+
+
+class AutotestGatherer(TableFormatter):
+
+ def __init__(self):
+ self.runs = []
+ TableFormatter.__init__(self)
+
+ def GetFormattedMainTable(self, percents_only, fit_string):
+ ret = ''
+ table = self.GetTableValues()
+ ret += self.GetTableLabels(table)
+ ret += self.GetFormattedTable(table,
+ percents_only=percents_only,
+ fit_string=fit_string)
+ return ret
+
+ def GetFormattedSummaryTable(self, percents_only, fit_string):
+ ret = ''
+ table = self.GetTableValues()
+ summary_table = self.GetSummaryTableValues(table)
+ ret += self.GetTableLabels(summary_table)
+ ret += self.GetFormattedTable(summary_table,
+ percents_only=percents_only,
+ fit_string=fit_string)
+ return ret
+
+ def GetBenchmarksString(self):
+ ret = 'Benchmarks (in order):'
+ ret = '\n'.join(self.GetAllBenchmarks())
+ return ret
+
+ def GetAllBenchmarks(self):
+ all_benchmarks = []
+ for run in self.runs:
+ for key in run.results.keys():
+ if key not in all_benchmarks:
+ all_benchmarks.append(key)
+ all_benchmarks.sort()
+ return all_benchmarks
+
+ def GetTableValues(self):
+ table = []
+ row = []
+
+ row.append('Benchmark')
+ for i in range(len(self.runs)):
+ run = self.runs[i]
+ label = run.GetLabel()
+ label = self.GetLabelWithIteration(label, run.iteration)
+ row.append(label)
+ table.append(row)
+
+ all_benchmarks = self.GetAllBenchmarks()
+ for benchmark in all_benchmarks:
+ row = []
+ row.append(benchmark)
+ for run in self.runs:
+ results = run.results
+ if benchmark in results:
+ row.append(results[benchmark])
+ else:
+ row.append('')
+ table.append(row)
+
+ return table
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)
diff --git a/deprecated/crb/crb_driver.py b/deprecated/crb/crb_driver.py
new file mode 100755
index 00000000..c6403462
--- /dev/null
+++ b/deprecated/crb/crb_driver.py
@@ -0,0 +1,370 @@
+#!/usr/bin/python2
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+
+import datetime
+import optparse
+import os
+import smtplib
+import sys
+import time
+from email.mime.text import MIMEText
+
+from autotest_gatherer import AutotestGatherer as AutotestGatherer
+from autotest_run import AutotestRun as AutotestRun
+from machine_manager_singleton import MachineManagerSingleton as MachineManagerSingleton
+from cros_utils import logger
+from cros_utils.file_utils import FileUtils
+
+
+def CanonicalizeChromeOSRoot(chromeos_root):
+ chromeos_root = os.path.expanduser(chromeos_root)
+ if os.path.isfile(os.path.join(chromeos_root, 'src/scripts/enter_chroot.sh')):
+ return chromeos_root
+ else:
+ return None
+
+
+class Autotest(object):
+
+ def __init__(self, autotest_string):
+ self.name = None
+ self.iterations = None
+ self.args = None
+ fields = autotest_string.split(',', 1)
+ self.name = fields[0]
+ if len(fields) > 1:
+ autotest_string = fields[1]
+ fields = autotest_string.split(',', 1)
+ else:
+ return
+ self.iterations = int(fields[0])
+ if len(fields) > 1:
+ self.args = fields[1]
+ else:
+ return
+
+ def __str__(self):
+ return '\n'.join([self.name, self.iterations, self.args])
+
+
+def CreateAutotestListFromString(autotest_strings, default_iterations=None):
+ autotest_list = []
+ for autotest_string in autotest_strings.split(':'):
+ autotest = Autotest(autotest_string)
+ if default_iterations and not autotest.iterations:
+ autotest.iterations = default_iterations
+
+ autotest_list.append(autotest)
+ return autotest_list
+
+
+def CreateAutotestRuns(images,
+ autotests,
+ remote,
+ board,
+ exact_remote,
+ rerun,
+ rerun_if_failed,
+ main_chromeos_root=None):
+ autotest_runs = []
+ for image in images:
+ logger.GetLogger().LogOutput('Computing md5sum of: %s' % image)
+ image_checksum = FileUtils().Md5File(image)
+ logger.GetLogger().LogOutput('md5sum %s: %s' % (image, image_checksum))
+ ### image_checksum = "abcdefghi"
+
+ chromeos_root = main_chromeos_root
+ if not main_chromeos_root:
+ image_chromeos_root = os.path.join(
+ os.path.dirname(image), '../../../../..')
+ chromeos_root = CanonicalizeChromeOSRoot(image_chromeos_root)
+ assert chromeos_root, 'chromeos_root: %s invalid' % image_chromeos_root
+ else:
+ chromeos_root = CanonicalizeChromeOSRoot(main_chromeos_root)
+ assert chromeos_root, 'chromeos_root: %s invalid' % main_chromeos_root
+
+ # We just need a single ChromeOS root in the MachineManagerSingleton. It is
+ # needed because we can save re-image time by checking the image checksum at
+ # the beginning and assigning autotests to machines appropriately.
+ if not MachineManagerSingleton().chromeos_root:
+ MachineManagerSingleton().chromeos_root = chromeos_root
+
+ for autotest in autotests:
+ for iteration in range(autotest.iterations):
+ autotest_run = AutotestRun(autotest,
+ chromeos_root=chromeos_root,
+ chromeos_image=image,
+ board=board,
+ remote=remote,
+ iteration=iteration,
+ image_checksum=image_checksum,
+ exact_remote=exact_remote,
+ rerun=rerun,
+ rerun_if_failed=rerun_if_failed)
+ autotest_runs.append(autotest_run)
+ return autotest_runs
+
+
+def GetNamesAndIterations(autotest_runs):
+ strings = []
+ for autotest_run in autotest_runs:
+ strings.append('%s:%s' % (autotest_run.autotest.name,
+ autotest_run.iteration))
+ return ' %s (%s)' % (len(strings), ' '.join(strings))
+
+
+def GetStatusString(autotest_runs):
+ status_bins = {}
+ for autotest_run in autotest_runs:
+ if autotest_run.status not in status_bins:
+ status_bins[autotest_run.status] = []
+ status_bins[autotest_run.status].append(autotest_run)
+
+ status_strings = []
+ for key, val in status_bins.items():
+ status_strings.append('%s: %s' % (key, GetNamesAndIterations(val)))
+ return 'Thread Status:\n%s' % '\n'.join(status_strings)
+
+
+def GetProgressBar(num_done, num_total):
+ ret = 'Done: %s%%' % int(100.0 * num_done / num_total)
+ bar_length = 50
+ done_char = '>'
+ undone_char = ' '
+ num_done_chars = bar_length * num_done / num_total
+ num_undone_chars = bar_length - num_done_chars
+ ret += ' [%s%s]' % (num_done_chars * done_char,
+ num_undone_chars * undone_char)
+ return ret
+
+
+def GetProgressString(start_time, num_remain, num_total):
+ current_time = time.time()
+ elapsed_time = current_time - start_time
+ try:
+ eta_seconds = float(num_remain) * elapsed_time / (num_total - num_remain)
+ eta_seconds = int(eta_seconds)
+ eta = datetime.timedelta(seconds=eta_seconds)
+ except ZeroDivisionError:
+ eta = 'Unknown'
+ strings = []
+ strings.append('Current time: %s Elapsed: %s ETA: %s' %
+ (datetime.datetime.now(),
+ datetime.timedelta(seconds=int(elapsed_time)), eta))
+ strings.append(GetProgressBar(num_total - num_remain, num_total))
+ return '\n'.join(strings)
+
+
+def RunAutotestRunsInParallel(autotest_runs):
+ start_time = time.time()
+ active_threads = []
+ for autotest_run in autotest_runs:
+ # Set threads to daemon so program exits when ctrl-c is pressed.
+ autotest_run.daemon = True
+ autotest_run.start()
+ active_threads.append(autotest_run)
+
+ print_interval = 30
+ last_printed_time = time.time()
+ while active_threads:
+ try:
+ active_threads = [t for t in active_threads
+ if t is not None and t.isAlive()]
+ for t in active_threads:
+ t.join(1)
+ if time.time() - last_printed_time > print_interval:
+ border = '=============================='
+ logger.GetLogger().LogOutput(border)
+ logger.GetLogger().LogOutput(GetProgressString(start_time, len(
+ [t for t in autotest_runs if t.status not in ['SUCCEEDED', 'FAILED']
+ ]), len(autotest_runs)))
+ logger.GetLogger().LogOutput(GetStatusString(autotest_runs))
+ logger.GetLogger().LogOutput('%s\n' %
+ MachineManagerSingleton().AsString())
+ logger.GetLogger().LogOutput(border)
+ last_printed_time = time.time()
+ except KeyboardInterrupt:
+ print 'C-c received... cleaning up threads.'
+ for t in active_threads:
+ t.terminate = True
+ return 1
+ return 0
+
+
+def RunAutotestRunsSerially(autotest_runs):
+ for autotest_run in autotest_runs:
+ retval = autotest_run.Run()
+ if retval:
+ return retval
+
+
+def ProduceTables(autotest_runs, full_table, fit_string):
+ l = logger.GetLogger()
+ ags_dict = {}
+ for autotest_run in autotest_runs:
+ name = autotest_run.full_name
+ if name not in ags_dict:
+ ags_dict[name] = AutotestGatherer()
+ ags_dict[name].runs.append(autotest_run)
+ output = ''
+ for b, ag in ags_dict.items():
+ output += 'Benchmark: %s\n' % b
+ output += ag.GetFormattedMainTable(percents_only=not full_table,
+ fit_string=fit_string)
+ output += '\n'
+
+ summary = ''
+ for b, ag in ags_dict.items():
+ summary += 'Benchmark Summary Table: %s\n' % b
+ summary += ag.GetFormattedSummaryTable(percents_only=not full_table,
+ fit_string=fit_string)
+ summary += '\n'
+
+ output += summary
+ output += ('Number of re-images performed: %s' %
+ MachineManagerSingleton().num_reimages)
+ l.LogOutput(output)
+
+ if autotest_runs:
+ board = autotest_runs[0].board
+ else:
+ board = ''
+
+ subject = '%s: %s' % (board, ', '.join(ags_dict.keys()))
+
+ if any(autotest_run.run_completed for autotest_run in autotest_runs):
+ SendEmailToUser(subject, summary)
+
+
+def SendEmailToUser(subject, text_to_send):
+ # Email summary to the current user.
+ msg = MIMEText(text_to_send)
+
+ # me == the sender's email address
+ # you == the recipient's email address
+ me = os.path.basename(__file__)
+ you = os.getlogin()
+ msg['Subject'] = '[%s] %s' % (os.path.basename(__file__), subject)
+ msg['From'] = me
+ msg['To'] = you
+
+ # Send the message via our own SMTP server, but don't include the
+ # envelope header.
+ s = smtplib.SMTP('localhost')
+ s.sendmail(me, [you], msg.as_string())
+ s.quit()
+
+
+def Main(argv):
+ """The main function."""
+ # Common initializations
+ ### command_executer.InitCommandExecuter(True)
+ l = logger.GetLogger()
+
+ parser = optparse.OptionParser()
+ parser.add_option('-t',
+ '--tests',
+ dest='tests',
+ help=('Tests to compare.'
+ 'Optionally specify per-test iterations by:'
+ '<test>,<iter>:<args>'))
+ parser.add_option('-c',
+ '--chromeos_root',
+ dest='chromeos_root',
+ help='A *single* chromeos_root where scripts can be found.')
+ parser.add_option('-n',
+ '--iterations',
+ dest='iterations',
+ help='Iterations to run per benchmark.',
+ default=1)
+ parser.add_option('-r',
+ '--remote',
+ dest='remote',
+ help='The remote chromeos machine.')
+ parser.add_option('-b', '--board', dest='board', help='The remote board.')
+ parser.add_option('--full_table',
+ dest='full_table',
+ help='Print full tables.',
+ action='store_true',
+ default=True)
+ parser.add_option('--exact_remote',
+ dest='exact_remote',
+ help='Run tests on the exact remote.',
+ action='store_true',
+ default=False)
+ parser.add_option('--fit_string',
+ dest='fit_string',
+ help='Fit strings to fixed sizes.',
+ action='store_true',
+ default=False)
+ parser.add_option('--rerun',
+ dest='rerun',
+ help='Re-run regardless of cache hit.',
+ action='store_true',
+ default=False)
+ parser.add_option('--rerun_if_failed',
+ dest='rerun_if_failed',
+ help='Re-run if previous run was a failure.',
+ action='store_true',
+ default=False)
+ parser.add_option('--no_lock',
+ dest='no_lock',
+ help='Do not lock the machine before running the tests.',
+ action='store_true',
+ default=False)
+ l.LogOutput(' '.join(argv))
+ [options, args] = parser.parse_args(argv)
+
+ if options.remote is None:
+ l.LogError('No remote machine specified.')
+ parser.print_help()
+ return 1
+
+ if not options.board:
+ l.LogError('No board specified.')
+ parser.print_help()
+ return 1
+
+ remote = options.remote
+ tests = options.tests
+ board = options.board
+ exact_remote = options.exact_remote
+ iterations = int(options.iterations)
+
+ autotests = CreateAutotestListFromString(tests, iterations)
+
+ main_chromeos_root = options.chromeos_root
+ images = args[1:]
+ fit_string = options.fit_string
+ full_table = options.full_table
+ rerun = options.rerun
+ rerun_if_failed = options.rerun_if_failed
+
+ MachineManagerSingleton().no_lock = options.no_lock
+
+ # Now try creating all the Autotests
+ autotest_runs = CreateAutotestRuns(images, autotests, remote, board,
+ exact_remote, rerun, rerun_if_failed,
+ main_chromeos_root)
+
+ try:
+ # At this point we have all the autotest runs.
+ for machine in remote.split(','):
+ MachineManagerSingleton().AddMachine(machine)
+
+ retval = RunAutotestRunsInParallel(autotest_runs)
+ if retval:
+ return retval
+
+ # Now print tables
+ ProduceTables(autotest_runs, full_table, fit_string)
+ finally:
+ # not sure why this isn't called at the end normally...
+ MachineManagerSingleton().__del__()
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/deprecated/crb/machine_manager_singleton.py b/deprecated/crb/machine_manager_singleton.py
new file mode 100644
index 00000000..6ffe9684
--- /dev/null
+++ b/deprecated/crb/machine_manager_singleton.py
@@ -0,0 +1,153 @@
+import image_chromeos
+import lock_machine
+import sys
+import threading
+import time
+from cros_utils import command_executer
+from cros_utils import logger
+
+
+class CrosMachine(object):
+
+ def __init__(self, name):
+ self.name = name
+ self.image = None
+ self.checksum = None
+ self.locked = False
+ self.released_time = time.time()
+ self.autotest_run = None
+
+ def __str__(self):
+ l = []
+ l.append(self.name)
+ l.append(str(self.image))
+ l.append(str(self.checksum))
+ l.append(str(self.locked))
+ l.append(str(self.released_time))
+ return ', '.join(l)
+
+
+class MachineManagerSingleton(object):
+ _instance = None
+ _lock = threading.RLock()
+ _all_machines = []
+ _machines = []
+ image_lock = threading.Lock()
+ num_reimages = 0
+ chromeos_root = None
+ no_lock = False
+
+ def __new__(cls, *args, **kwargs):
+ with cls._lock:
+ if not cls._instance:
+ cls._instance = super(MachineManagerSingleton, cls).__new__(cls, *args,
+ **kwargs)
+ return cls._instance
+
+ def TryToLockMachine(self, cros_machine):
+ with self._lock:
+ assert cros_machine, "Machine can't be None"
+ for m in self._machines:
+ assert m.name != cros_machine.name, ('Tried to double-lock %s' %
+ cros_machine.name)
+ if self.no_lock:
+ locked = True
+ else:
+ locked = lock_machine.Machine(cros_machine.name).Lock(True, sys.argv[0])
+ if locked:
+ ce = command_executer.GetCommandExecuter()
+ command = 'cat %s' % image_chromeos.checksum_file
+ ret, out, err = ce.CrosRunCommandWOutput(
+ command,
+ chromeos_root=self.chromeos_root,
+ machine=cros_machine.name)
+ if ret == 0:
+ cros_machine.checksum = out.strip()
+ self._machines.append(cros_machine)
+ else:
+ logger.GetLogger().LogOutput("Warning: Couldn't lock: %s" %
+ cros_machine.name)
+
+ # This is called from single threaded mode.
+ def AddMachine(self, machine_name):
+ with self._lock:
+ for m in self._all_machines:
+ assert m.name != machine_name, 'Tried to double-add %s' % machine_name
+ self._all_machines.append(CrosMachine(machine_name))
+
+ def AcquireMachine(self, image_checksum):
+ with self._lock:
+ # Lazily external lock machines
+ if not self._machines:
+ for m in self._all_machines:
+ self.TryToLockMachine(m)
+ assert self._machines, ('Could not lock any machine in %s' %
+ self._all_machines)
+
+ ### for m in self._machines:
+ ### if (m.locked and time.time() - m.released_time < 10 and
+ ### m.checksum == image_checksum):
+ ### return None
+ for m in [machine for machine in self._machines if not machine.locked]:
+ if m.checksum == image_checksum:
+ m.locked = True
+ m.autotest_run = threading.current_thread()
+ return m
+ for m in [machine for machine in self._machines if not machine.locked]:
+ if not m.checksum:
+ m.locked = True
+ m.autotest_run = threading.current_thread()
+ return m
+ for m in [machine for machine in self._machines if not machine.locked]:
+ if time.time() - m.released_time > 20:
+ m.locked = True
+ m.autotest_run = threading.current_thread()
+ return m
+ return None
+
+ def ReleaseMachine(self, machine):
+ with self._lock:
+ for m in self._machines:
+ if machine.name == m.name:
+ assert m.locked == True, 'Tried to double-release %s' % m.name
+ m.released_time = time.time()
+ m.locked = False
+ m.status = 'Available'
+ break
+
+ def __del__(self):
+ with self._lock:
+ # Unlock all machines.
+ for m in self._machines:
+ if not self.no_lock:
+ assert lock_machine.Machine(m.name).Unlock(True) == True, (
+ "Couldn't unlock machine: %s" % m.name)
+
+ def __str__(self):
+ with self._lock:
+ l = ['MachineManager Status:']
+ for m in self._machines:
+ l.append(str(m))
+ return '\n'.join(l)
+
+ def AsString(self):
+ with self._lock:
+ stringify_fmt = '%-30s %-10s %-4s %-25s %-32s'
+ header = stringify_fmt % ('Machine', 'Thread', 'Lock', 'Status',
+ 'Checksum')
+ table = [header]
+ for m in self._machines:
+ if m.autotest_run:
+ autotest_name = m.autotest_run.name
+ autotest_status = m.autotest_run.status
+ else:
+ autotest_name = ''
+ autotest_status = ''
+
+ try:
+ machine_string = stringify_fmt % (m.name, autotest_name, m.locked,
+ autotest_status, m.checksum)
+ except:
+ machine_string = ''
+ table.append(machine_string)
+ return 'Machine Status:\n%s' % '\n'.join(table)
diff --git a/deprecated/crb/table_formatter.py b/deprecated/crb/table_formatter.py
new file mode 100644
index 00000000..b8e25d5f
--- /dev/null
+++ b/deprecated/crb/table_formatter.py
@@ -0,0 +1,258 @@
+import numpy
+import re
+
+
+def IsFloat(text):
+ if text is None:
+ return False
+ try:
+ float(text)
+ return True
+ except ValueError:
+ return False
+
+
+def RemoveTrailingZeros(x):
+ ret = x
+ ret = re.sub('\.0*$', '', ret)
+ ret = re.sub('(\.[1-9]*)0+$', '\\1', ret)
+ return ret
+
+
+def HumanizeFloat(x, n=2):
+ if not IsFloat(x):
+ return x
+ digits = re.findall('[0-9.]', str(x))
+ decimal_found = False
+ ret = ''
+ sig_figs = 0
+ for digit in digits:
+ if digit == '.':
+ decimal_found = True
+ elif sig_figs != 0 or digit != '0':
+ sig_figs += 1
+ if decimal_found and sig_figs >= n:
+ break
+ ret += digit
+ return ret
+
+
+def GetNSigFigs(x, n=2):
+ if not IsFloat(x):
+ return x
+ my_fmt = '%.' + str(n - 1) + 'e'
+ x_string = my_fmt % x
+ f = float(x_string)
+ return f
+
+
+def GetFormattedPercent(baseline, other, bad_result='--'):
+ result = '%8s' % GetPercent(baseline, other, bad_result)
+ return result
+
+
+def GetPercent(baseline, other, bad_result='--'):
+ result = bad_result
+ if IsFloat(baseline) and IsFloat(other):
+ try:
+ pct = (float(other) / float(baseline) - 1) * 100
+ result = '%+1.1f' % pct
+ except ZeroDivisionError:
+ pass
+ return result
+
+
+def FitString(text, length):
+ if len(text) == length:
+ return text
+ elif len(text) > length:
+ return text[-length:]
+ else:
+ fmt = '%%%ds' % length
+ return fmt % text
+
+
+class TableFormatter(object):
+
+ def __init__(self):
+ self.d = '\t'
+ self.bad_result = 'x'
+
+ def GetTablePercents(self, table):
+ # Assumes table is not transposed.
+ pct_table = []
+
+ pct_table.append(table[0])
+ for i in range(1, len(table)):
+ row = []
+ row.append(table[i][0])
+ for j in range(1, len(table[0])):
+ c = table[i][j]
+ b = table[i][1]
+ p = GetPercent(b, c, self.bad_result)
+ row.append(p)
+ pct_table.append(row)
+ return pct_table
+
+ def FormatFloat(self, c, max_length=8):
+ if not IsFloat(c):
+ return c
+ f = float(c)
+ ret = HumanizeFloat(f, 4)
+ ret = RemoveTrailingZeros(ret)
+ if len(ret) > max_length:
+ ret = '%1.1ef' % f
+ return ret
+
+ def TransposeTable(self, table):
+ transposed_table = []
+ for i in range(len(table[0])):
+ row = []
+ for j in range(len(table)):
+ row.append(table[j][i])
+ transposed_table.append(row)
+ return transposed_table
+
+ def GetTableLabels(self, table):
+ ret = ''
+ header = table[0]
+ for i in range(1, len(header)):
+ ret += '%d: %s\n' % (i, header[i])
+ return ret
+
+ def GetFormattedTable(self,
+ table,
+ transposed=False,
+ first_column_width=30,
+ column_width=14,
+ percents_only=True,
+ fit_string=True):
+ o = ''
+ pct_table = self.GetTablePercents(table)
+ if transposed == True:
+ table = self.TransposeTable(table)
+ pct_table = self.TransposeTable(table)
+
+ for i in range(0, len(table)):
+ for j in range(len(table[0])):
+ if j == 0:
+ width = first_column_width
+ else:
+ width = column_width
+
+ c = table[i][j]
+ p = pct_table[i][j]
+
+ # Replace labels with numbers: 0... n
+ if IsFloat(c):
+ c = self.FormatFloat(c)
+
+ if IsFloat(p) and not percents_only:
+ p = '%s%%' % p
+
+ # Print percent values side by side.
+ if j != 0:
+ if percents_only:
+ c = '%s' % p
+ else:
+ c = '%s (%s)' % (c, p)
+
+ if i == 0 and j != 0:
+ c = str(j)
+
+ if fit_string:
+ o += FitString(c, width) + self.d
+ else:
+ o += c + self.d
+ o += '\n'
+ return o
+
+ def GetGroups(self, table):
+ labels = table[0]
+ groups = []
+ group_dict = {}
+ for i in range(1, len(labels)):
+ label = labels[i]
+ stripped_label = self.GetStrippedLabel(label)
+ if stripped_label not in group_dict:
+ group_dict[stripped_label] = len(groups)
+ groups.append([])
+ groups[group_dict[stripped_label]].append(i)
+ return groups
+
+ def GetSummaryTableValues(self, table):
+ # First get the groups
+ groups = self.GetGroups(table)
+
+ summary_table = []
+
+ labels = table[0]
+
+ summary_labels = ['Summary Table']
+ for group in groups:
+ label = labels[group[0]]
+ stripped_label = self.GetStrippedLabel(label)
+ group_label = '%s (%d runs)' % (stripped_label, len(group))
+ summary_labels.append(group_label)
+ summary_table.append(summary_labels)
+
+ for i in range(1, len(table)):
+ row = table[i]
+ summary_row = [row[0]]
+ for group in groups:
+ group_runs = []
+ for index in group:
+ group_runs.append(row[index])
+ group_run = self.AggregateResults(group_runs)
+ summary_row.append(group_run)
+ summary_table.append(summary_row)
+
+ return summary_table
+
+ # Drop N% slowest and M% fastest numbers, and return arithmean of
+ # the remaining.
+ @staticmethod
+ def AverageWithDrops(numbers, slow_percent=20, fast_percent=20):
+ sorted_numbers = list(numbers)
+ sorted_numbers.sort()
+ num_slow = int(slow_percent / 100.0 * len(sorted_numbers))
+ num_fast = int(fast_percent / 100.0 * len(sorted_numbers))
+ sorted_numbers = sorted_numbers[num_slow:]
+ if num_fast:
+ sorted_numbers = sorted_numbers[:-num_fast]
+ return numpy.average(sorted_numbers)
+
+ @staticmethod
+ def AggregateResults(group_results):
+ ret = ''
+ if not group_results:
+ return ret
+ all_floats = True
+ all_passes = True
+ all_fails = True
+ for group_result in group_results:
+ if not IsFloat(group_result):
+ all_floats = False
+ if group_result != 'PASSED':
+ all_passes = False
+ if group_result != 'FAILED':
+ all_fails = False
+ if all_floats == True:
+ float_results = [float(v) for v in group_results]
+ ret = '%f' % TableFormatter.AverageWithDrops(float_results)
+ # Add this line for standard deviation.
+ ### ret += " %f" % numpy.std(float_results)
+ elif all_passes == True:
+ ret = 'ALL_PASS'
+ elif all_fails == True:
+ ret = 'ALL_FAILS'
+ return ret
+
+ @staticmethod
+ def GetStrippedLabel(label):
+ return re.sub('\s*\S+:\S+\s*', '', label)
+### return re.sub("\s*remote:\S*\s*i:\d+$", "", label)
+
+ @staticmethod
+ def GetLabelWithIteration(label, iteration):
+ return '%s i:%d' % (label, iteration)