Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(641)

Unified Diff: tools/testing/perf_testing/run_perf_tests.py

Issue 10829408: Smarter "new interesting code" detection. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/testing/webdriver_test_setup.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/testing/perf_testing/run_perf_tests.py
===================================================================
--- tools/testing/perf_testing/run_perf_tests.py (revision 11181)
+++ tools/testing/perf_testing/run_perf_tests.py (working copy)
@@ -45,8 +45,9 @@
if platform.system() == 'Windows':
# On Windows, shell must be true to get the correct environment variables.
self.has_shell = True
+ self.current_revision_num = None
- def run_cmd(self, cmd_list, outfile=None, append=False, std_in=''):
+ def RunCmd(self, cmd_list, outfile=None, append=False, std_in=''):
"""Run the specified command and print out any output to stdout.
Args:
@@ -78,18 +79,18 @@
print stderr
return output, stderr
- def time_cmd(self, cmd):
+ def TimeCmd(self, cmd):
"""Determine the amount of (real) time it takes to execute a given
command."""
start = time.time()
- self.run_cmd(cmd)
+ self.RunCmd(cmd)
return time.time() - start
- def clear_out_unversioned_files(self):
+ def ClearOutUnversionedFiles(self):
"""Remove all files that are unversioned by svn."""
if os.path.exists(DART_REPO_LOC):
os.chdir(DART_REPO_LOC)
- results, _ = self.run_cmd(['svn', 'st'])
+ results, _ = self.RunCmd(['svn', 'st'])
for line in results.split('\n'):
if line.startswith('?'):
to_remove = line.split()[1]
@@ -98,32 +99,30 @@
else:
os.remove(to_remove)
- def get_archive(self, archive_name):
+ def GetArchive(self, archive_name):
"""Wrapper around the pulling down a specific archive from Google Storage.
Adds a specific revision argument as needed.
- Returns: The stderr from running this command."""
- cmd = ['python', os.path.join(DART_REPO_LOC, 'tools', 'get_archive.py'),
- archive_name]
- if self.current_revision_num != -1:
- cmd += ['-r', self.current_revision_num]
- _, stderr = self.run_cmd(cmd)
- return stderr
+ Returns: The stdout and stderr from running this command."""
+ while True:
+ cmd = ['python', os.path.join(DART_REPO_LOC, 'tools', 'get_archive.py'),
+ archive_name]
+ if int(self.current_revision_num) != -1:
+ cmd += ['-r', str(self.current_revision_num)]
+ stdout, stderr = self.RunCmd(cmd)
+ if 'Please try again later' in stdout:
+ time.sleep(100)
+ else:
+ break
+ return (stdout, stderr)
- def sync_and_build(self, suites, revision_num=''):
- """Make sure we have the latest version of of the repo, and build it. We
- begin and end standing in DART_REPO_LOC.
-
- Args:
- suites: The set of suites that we wish to build.
-
- Returns:
- err_code = 1 if there was a problem building."""
+ def _Sync(self, revision_num=None):
+ """Update the repository to the latest or specified revision."""
os.chdir(dirname(DART_REPO_LOC))
- self.clear_out_unversioned_files()
- if revision_num == '':
- self.run_cmd(['gclient', 'sync'])
+ self.ClearOutUnversionedFiles()
+ if not revision_num:
+ self.RunCmd(['gclient', 'sync'])
else:
- self.run_cmd(['gclient', 'sync', '-r', revision_num, '-t'])
+ self.RunCmd(['gclient', 'sync', '-r', str(revision_num), '-t'])
shutil.copytree(os.path.join(TOP_LEVEL_DIR, 'internal'),
os.path.join(DART_REPO_LOC, 'internal'))
@@ -133,14 +132,24 @@
os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'run_selenium.py'),
os.path.join(DART_REPO_LOC, 'tools', 'testing', 'run_selenium.py'))
- if revision_num == '':
- revision_num = search_for_revision()
+ def SyncAndBuild(self, suites, revision_num=None):
+ """Make sure we have the latest version of of the repo, and build it. We
+ begin and end standing in DART_REPO_LOC.
+ Args:
+ suites: The set of suites that we wish to build.
+
+ Returns:
+ err_code = 1 if there was a problem building."""
+ self._Sync(revision_num)
+ if not revision_num:
+ revision_num = SearchForRevision()
+
self.current_revision_num = revision_num
- stderr = self.get_archive('sdk')
- if not os.path.exists(os.path.join(
- DART_REPO_LOC, 'tools', 'get_archive.py')) \
- or 'InvalidUriError' in stderr:
+ stdout, stderr = self.GetArchive('sdk')
+ if (not os.path.exists(os.path.join(
+ DART_REPO_LOC, 'tools', 'get_archive.py'))
+ or 'InvalidUriError' in stderr or "Couldn't download" in stdout):
# Couldn't find the SDK on Google Storage. Build it locally.
# On Windows, the output directory is marked as "Read Only," which causes
@@ -156,7 +165,7 @@
shutil.rmtree(os.path.join(os.getcwd(),
utils.GetBuildRoot(utils.GuessOS(), 'release', 'ia32')),
onerror=on_rm_error)
- lines = self.run_cmd([os.path.join('.', 'tools', 'build.py'), '-m',
+ lines = self.RunCmd([os.path.join('.', 'tools', 'build.py'), '-m',
'release', '--arch=ia32', 'create_sdk'])
for line in lines:
@@ -167,7 +176,7 @@
return 1
return 0
- def ensure_output_directory(self, dir_name):
+ def EnsureOutputDirectory(self, dir_name):
"""Test that the listed directory name exists, and if not, create one for
our output to be placed.
@@ -179,49 +188,95 @@
os.makedirs(dir_path)
print 'Creating output directory ', dir_path
- def has_interesting_code(self, past_revision_num=None):
+ def HasInterestingCode(self, revision_num=None):
"""Tests if there are any versions of files that might change performance
- results on the server."""
+ results on the server.
+
+ Returns:
+ (False, None): There is no interesting code to run.
+ (True, revisionNumber): There is interesting code to run at revision
+ revisionNumber.
+ (True, None): There is interesting code to run by syncing to the
+ tip-of-tree."""
if not os.path.exists(DART_REPO_LOC):
- return True
+ self._Sync()
os.chdir(DART_REPO_LOC)
- no_effect = ['client', 'compiler', 'editor', 'pkg', 'samples', 'tests',
- 'third_party', 'tools', 'utils']
- # Pass 'p' in if we have a new certificate for the svn server, we want to
- # (p)ermanently accept it.
- if past_revision_num:
+ no_effect = ['dart/client', 'dart/compiler', 'dart/editor',
+ 'dart/lib/html/doc', 'dart/pkg', 'dart/tests', 'dart/samples',
+ 'dart/lib/dartdoc', 'dart/lib/i18n', 'dart/lib/unittest',
+ 'dart/tools/dartc', 'dart/tools/get_archive.py',
+ 'dart/tools/test.py', 'dart/tools/testing',
+ 'dart/tools/utils', 'dart/third_party', 'dart/utils']
+ definitely_yes = ['dart/samples/third_party/dromaeo',
+ 'dart/lib/html/dart2js', 'dart/lib/html/dartium',
+ 'dart/lib/scripts', 'dart/lib/src',
+ 'dart/third_party/WebCore']
+ def GetFileList(revision):
+ """Determine the set of files that were changed for a particular
+ revision."""
# TODO(efortuna): This assumes you're using svn. Have a git fallback as
- # well.
- results, _ = self.run_cmd(['svn', 'log', '-v', '-r',
- str(past_revision_num)], std_in='p\r\n')
+ # well. Pass 'p' in if we have a new certificate for the svn server, we
+ # want to (p)ermanently accept it.
+ results, _ = self.RunCmd([
+ 'svn', 'log', 'http://dart.googlecode.com/svn/branches/bleeding_edge',
+ '-v', '-r', str(revision)], std_in='p\r\n')
results = results.split('\n')
if len(results) <= 3:
- results = []
+ return []
else:
# Trim off the details about revision number and commit message. We're
# only interested in the files that are changed.
results = results[3:]
changed_files = []
for result in results:
- if result == '':
+ if len(result) <= 1:
break
- changed_files += [result.replace('/branches/bleeding_edge/dart/', '')]
- results = changed_files
+ tokens = result.split()
+ if len(tokens) > 1:
+ changed_files += [tokens[1].replace('/branches/bleeding_edge/', '')]
+ return changed_files
+
+ def HasPerfAffectingResults(files_list):
+ """Determine if this set of changed files might effect performance
+ tests."""
+ def IsSafeFile(f):
+ if not any(f.startswith(prefix) for prefix in definitely_yes):
+ return any(f.startswith(prefix) for prefix in no_effect)
+ return False
+ return not all(IsSafeFile(f) for f in files_list)
+
+ if revision_num:
+ return (HasPerfAffectingResults(GetFileList(
+ revision_num)), revision_num)
else:
- results, _ = self.run_cmd(['svn', 'st', '-u'], std_in='p\r\n')
- results = results.split('\n')
- for line in results:
- tokens = line.split()
- if past_revision_num or len(tokens) >= 3 and '*' in tokens[-3]:
- # Loop through the changed files to see if it contains any files that
- # are NOT listed in the no_effect list (directories not listed in
- # the "no_effect" list are assumed to potentially affect performance.
- if not reduce(lambda x, y: x or y,
- [tokens[-1].startswith(item) for item in no_effect], False):
- return True
- return False
+ results, _ = self.RunCmd(['svn', 'st', '-u'], std_in='p\r\n')
+ latest_interesting_server_rev = int(results.split('\n')[-2].split()[-1])
+ if self.backfill:
+ done_cls = list(UpdateSetOfDoneCls())
+ done_cls.sort()
+ if done_cls:
+ last_done_cl = int(done_cls[-1])
+ else:
+ last_done_cl = EARLIEST_REVISION
+ while latest_interesting_server_rev >= last_done_cl:
+ file_list = GetFileList(latest_interesting_server_rev)
+ if HasPerfAffectingResults(file_list):
+ return (True, latest_interesting_server_rev)
+ else:
+ UpdateSetOfDoneCls(latest_interesting_server_rev)
+ latest_interesting_server_rev -= 1
+ else:
+ last_done_cl = int(SearchForRevision(DART_REPO_LOC)) + 1
+ while last_done_cl <= latest_interesting_server_rev:
+ file_list = GetFileList(last_done_cl)
+ if HasPerfAffectingResults(file_list):
+ return (True, last_done_cl)
+ else:
+ UpdateSetOfDoneCls(last_done_cl)
+ last_done_cl += 1
+ return (False, None)
- def get_os_directory(self):
+ def GetOsDirectory(self):
"""Specifies the name of the directory for the testing build of dart, which
has yet a different naming convention from utils.getBuildRoot(...)."""
if platform.system() == 'Windows':
@@ -231,11 +286,11 @@
else:
return 'linux'
- def parse_args(self):
+ def ParseArgs(self):
parser = optparse.OptionParser()
parser.add_option('--suites', '-s', dest='suites', help='Run the specified '
'comma-separated test suites from set: %s' % \
- ','.join(TestBuilder.available_suite_names()),
+ ','.join(TestBuilder.AvailableSuiteNames()),
action='store', default=None)
parser.add_option('--forever', '-f', dest='continuous', help='Run this scri'
'pt forever, always checking for the next svn checkin',
@@ -247,46 +302,55 @@
help='Do not post the results of the run.', default=False)
parser.add_option('--notest', '-t', dest='no_test', action='store_true',
help='Do not run the tests.', default=False)
- parser.add_option('--verbose', '-v', dest='verbose', help='Print extra '
- 'debug output', action='store_true', default=False)
+ parser.add_option('--verbose', '-v', dest='verbose',
+ help='Print extra debug output', action='store_true',
+ default=False)
+ parser.add_option('--backfill', '-b', dest='backfill',
+ help='Backfill earlier CLs with additional results when '
+ 'there is idle time.', action='store_true',
+ default=False)
args, ignored = parser.parse_args()
if not args.suites:
- suites = TestBuilder.available_suite_names()
+ suites = TestBuilder.AvailableSuiteNames()
else:
suites = []
suitelist = args.suites.split(',')
for name in suitelist:
- if name in TestBuilder.available_suite_names():
+ if name in TestBuilder.AvailableSuiteNames():
suites.append(name)
else:
print ('Error: Invalid suite %s not in ' % name) + \
- '%s' % ','.join(TestBuilder.available_suite_names())
+ '%s' % ','.join(TestBuilder.AvailableSuiteNames())
sys.exit(1)
self.suite_names = suites
self.no_build = args.no_build
self.no_upload = args.no_upload
self.no_test = args.no_test
self.verbose = args.verbose
+ self.backfill = args.backfill
return args.continuous
- def run_test_sequence(self, revision_num='', num_reruns=1):
+ def RunTestSequence(self, revision_num=None, num_reruns=1):
"""Run the set of commands to (possibly) build, run, and post the results
of our tests. Returns 0 on a successful run, 1 if we fail to post results or
the run failed, -1 if the build is broken.
"""
suites = []
success = True
- if not self.no_build and self.sync_and_build(suites, revision_num) == 1:
+ if not self.no_build and self.SyncAndBuild(suites, revision_num) == 1:
return -1 # The build is broken.
+ if not self.current_revision_num:
+ self.current_revision_num = SearchForRevision(DART_REPO_LOC)
+
for name in self.suite_names:
for run in range(num_reruns):
- suites += [TestBuilder.make_test(name, self)]
+ suites += [TestBuilder.MakeTest(name, self)]
for test in suites:
- success = success and test.run()
+ success = success and test.Run()
if success:
return 0
else:
@@ -343,7 +407,7 @@
self.revision_dict[platform][f][extra_metric] = []
self.values_dict[platform][f][extra_metric] = []
- def is_valid_combination(self, platform, variant):
+ def IsValidCombination(self, platform, variant):
"""Check whether data should be captured for this platform/variant
combination.
"""
@@ -360,20 +424,20 @@
return False
return True
- def run(self):
+ def Run(self):
"""Run the benchmarks/tests from the command line and plot the
results.
"""
for visitor in [self.tester, self.file_processor]:
- visitor.prepare()
+ visitor.Prepare()
os.chdir(TOP_LEVEL_DIR)
- self.test_runner.ensure_output_directory(self.result_folder_name)
- self.test_runner.ensure_output_directory(os.path.join(
+ self.test_runner.EnsureOutputDirectory(self.result_folder_name)
+ self.test_runner.EnsureOutputDirectory(os.path.join(
'old', self.result_folder_name))
os.chdir(DART_REPO_LOC)
if not self.test_runner.no_test:
- self.tester.run_tests()
+ self.tester.RunTests()
os.chdir(os.path.join(TOP_LEVEL_DIR, 'tools', 'testing', 'perf_testing'))
@@ -381,7 +445,7 @@
post_success = True
for afile in files:
if not afile.startswith('.'):
- should_move_file = self.file_processor.process_file(afile, True)
+ should_move_file = self.file_processor.ProcessFile(afile, True)
if should_move_file:
shutil.move(os.path.join(self.result_folder_name, afile),
os.path.join('old', self.result_folder_name, afile))
@@ -394,16 +458,16 @@
class Tester(object):
"""The base level visitor class that runs tests. It contains convenience
methods that many Tester objects use. Any class that would like to be a
- TesterVisitor must implement the run_tests() method."""
+ TesterVisitor must implement the RunTests() method."""
def __init__(self, test):
self.test = test
- def prepare(self):
+ def Prepare(self):
"""Perform any initial setup required before the test is run."""
pass
- def add_svn_revision_to_trace(self, outfile, browser = None):
+ def AddSvnRevisionToTrace(self, outfile, browser = None):
"""Add the svn version number to the provided tracefile."""
def get_dartium_revision():
version_file_name = os.path.join(DART_REPO_LOC, 'client', 'tests',
@@ -415,16 +479,16 @@
if browser and browser == 'dartium':
revision = get_dartium_revision()
- self.test.test_runner.run_cmd(['echo', 'Revision: ' + revision], outfile)
+ self.test.test_runner.RunCmd(['echo', 'Revision: ' + revision], outfile)
else:
- revision = search_for_revision()
- self.test.test_runner.run_cmd(['echo', 'Revision: ' + revision], outfile)
+ revision = SearchForRevision()
+ self.test.test_runner.RunCmd(['echo', 'Revision: ' + revision], outfile)
class Processor(object):
"""The base level vistor class that processes tests. It contains convenience
methods that many File Processor objects use. Any class that would like to be
- a ProcessorVisitor must implement the process_file() method."""
+ a ProcessorVisitor must implement the ProcessFile() method."""
SCORE = 'Score'
COMPILE_TIME = 'CompileTime'
@@ -433,11 +497,11 @@
def __init__(self, test):
self.test = test
- def prepare(self):
+ def Prepare(self):
"""Perform any initial setup required before the test is run."""
pass
- def open_trace_file(self, afile, not_yet_uploaded):
+ def OpenTraceFile(self, afile, not_yet_uploaded):
"""Find the correct location for the trace file, and open it.
Args:
afile: The tracefile name.
@@ -449,7 +513,7 @@
file_path = os.path.join('old', file_path)
return open(file_path)
- def report_results(self, benchmark_name, score, platform, variant,
+ def ReportResults(self, benchmark_name, score, platform, variant,
revision_number, metric):
"""Store the results of the benchmark run.
Args:
@@ -465,21 +529,24 @@
return post_results.report_results(benchmark_name, score, platform, variant,
revision_number, metric)
- def calculate_geometric_mean(self, platform, variant, svn_revision):
+ def CalculateGeometricMean(self, platform, variant, svn_revision):
"""Calculate the aggregate geometric mean for JS and dart2js benchmark sets,
given two benchmark dictionaries."""
geo_mean = 0
- if self.test.is_valid_combination(platform, variant):
+ if self.test.IsValidCombination(platform, variant):
for benchmark in self.test.values_list:
+ if not self.test.values_dict[platform][variant][benchmark]:
+ print 'Error determining mean for %s %s %s' % (platform, variant,
+ benchmark)
+ continue
geo_mean += math.log(
- self.test.values_dict[platform][variant][benchmark][
- len(self.test.values_dict[platform][variant][benchmark]) - 1])
+ self.test.values_dict[platform][variant][benchmark][-1])
self.test.values_dict[platform][variant]['Geo-Mean'] += \
[math.pow(math.e, geo_mean / len(self.test.values_list))]
self.test.revision_dict[platform][variant]['Geo-Mean'] += [svn_revision]
- def get_score_type(self, benchmark_name):
+ def GetScoreType(self, benchmark_name):
"""Determine the type of score for posting -- default is 'Score' (aka
Runtime), other options are CompileTime and CodeSize."""
return self.SCORE
@@ -518,8 +585,8 @@
class BrowserTester(Tester):
@staticmethod
- def get_browsers(add_dartium=True):
- browsers = []#['ff', 'chrome']
+ def GetBrowsers(add_dartium=True):
+ browsers = ['ff', 'chrome']
if add_dartium:
browsers += ['dartium']
has_shell = False
@@ -539,43 +606,43 @@
"""Args:
test_runner: Reference to the object that notifies us when to run."""
super(CommonBrowserTest, self).__init__(
- self.name(), BrowserTester.get_browsers(False),
+ self.Name(), BrowserTester.GetBrowsers(False),
'browser', ['js', 'dart2js'],
- self.get_standalone_benchmarks(), test_runner,
+ self.GetStandaloneBenchmarks(), test_runner,
self.CommonBrowserTester(self),
self.CommonBrowserFileProcessor(self))
@staticmethod
- def name():
+ def Name():
return 'browser-perf'
@staticmethod
- def get_standalone_benchmarks():
+ def GetStandaloneBenchmarks():
return ['Mandelbrot', 'DeltaBlue', 'Richards', 'NBody', 'BinaryTrees',
'Fannkuch', 'Meteor', 'BubbleSort', 'Fibonacci', 'Loop', 'Permute',
'Queens', 'QuickSort', 'Recurse', 'Sieve', 'Sum', 'Tak', 'Takl', 'Towers',
'TreeSort']
class CommonBrowserTester(BrowserTester):
- def run_tests(self):
+ def RunTests(self):
"""Run a performance test in the browser."""
os.chdir(DART_REPO_LOC)
- self.test.test_runner.run_cmd([
+ self.test.test_runner.RunCmd([
'python', os.path.join('internal', 'browserBenchmarks',
'make_web_benchmarks.py')])
for browser in self.test.platform_list:
for version in self.test.versions:
- if not self.test.is_valid_combination(browser, version):
+ if not self.test.IsValidCombination(browser, version):
continue
self.test.trace_file = os.path.join(TOP_LEVEL_DIR,
'tools', 'testing', 'perf_testing', self.test.result_folder_name,
'perf-%s-%s-%s' % (self.test.cur_time, browser, version))
- self.add_svn_revision_to_trace(self.test.trace_file, browser)
+ self.AddSvnRevisionToTrace(self.test.trace_file, browser)
file_path = os.path.join(
os.getcwd(), 'internal', 'browserBenchmarks',
'benchmark_page_%s.html' % version)
- self.test.test_runner.run_cmd(
+ self.test.test_runner.RunCmd(
['python', os.path.join('tools', 'testing', 'run_selenium.py'),
'--out', file_path, '--browser', browser,
'--timeout', '600', '--mode', 'perf'], self.test.trace_file,
@@ -583,7 +650,7 @@
class CommonBrowserFileProcessor(Processor):
- def process_file(self, afile, should_post_file):
+ def ProcessFile(self, afile, should_post_file):
"""Comb through the html to find the performance results.
Returns: True if we successfully posted our data to storage and/or we can
delete the trace file."""
@@ -592,7 +659,7 @@
parts = afile.split('-')
browser = parts[2]
version = parts[3]
- f = self.open_trace_file(afile, should_post_file)
+ f = self.OpenTraceFile(afile, should_post_file)
lines = f.readlines()
line = ''
i = 0
@@ -629,14 +696,14 @@
bench_dict[name] += [float(score)]
self.test.revision_dict[browser][version][name] += [revision_num]
if not self.test.test_runner.no_upload and should_post_file:
- upload_success = upload_success and self.report_results(
+ upload_success = upload_success and self.ReportResults(
name, score, browser, version, revision_num,
- self.get_score_type(name))
+ self.GetScoreType(name))
else:
upload_success = False
f.close()
- self.calculate_geometric_mean(browser, version, revision_num)
+ self.CalculateGeometricMean(browser, version, revision_num)
return upload_success
@@ -674,7 +741,7 @@
# Use filenames that don't have unusual characters for benchmark names.
@staticmethod
- def legalize_filename(str):
+ def LegalizeFilename(str):
remap = {
' ': '_',
'(': '_',
@@ -690,23 +757,23 @@
# failure properly. The modify suite fails on 32-bit chrome, which
# is the default on mac and win.
@staticmethod
- def get_valid_dromaeo_tags():
+ def GetValidDromaeoTags():
tags = [tag for (tag, _) in DromaeoTester.DROMAEO_BENCHMARKS.values()]
if platform.system() == 'Darwin' or platform.system() == 'Windows':
tags.remove('modify')
return tags
@staticmethod
- def get_dromaeo_benchmarks():
- valid = DromaeoTester.get_valid_dromaeo_tags()
+ def GetDromaeoBenchmarks():
+ valid = DromaeoTester.GetValidDromaeoTags()
benchmarks = reduce(lambda l1,l2: l1+l2,
[tests for (tag, tests) in
DromaeoTester.DROMAEO_BENCHMARKS.values()
if tag in valid])
- return map(DromaeoTester.legalize_filename, benchmarks)
+ return map(DromaeoTester.LegalizeFilename, benchmarks)
@staticmethod
- def get_dromaeo_versions():
+ def GetDromaeoVersions():
return ['js', 'dart2js_html']
@@ -714,20 +781,20 @@
"""Runs Dromaeo tests, in the browser."""
def __init__(self, test_runner):
super(DromaeoTest, self).__init__(
- self.name(),
- BrowserTester.get_browsers(True),
+ self.Name(),
+ BrowserTester.GetBrowsers(True),
'browser',
- DromaeoTester.get_dromaeo_versions(),
- DromaeoTester.get_dromaeo_benchmarks(), test_runner,
+ DromaeoTester.GetDromaeoVersions(),
+ DromaeoTester.GetDromaeoBenchmarks(), test_runner,
self.DromaeoPerfTester(self),
self.DromaeoFileProcessor(self))
@staticmethod
- def name():
+ def Name():
return 'dromaeo'
class DromaeoPerfTester(DromaeoTester):
- def move_chrome_driver_if_needed(self, browser):
+ def MoveChromeDriverIfNeeded(self, browser):
"""Move the appropriate version of ChromeDriver onto the path.
TODO(efortuna): This is a total hack because the latest version of Chrome
(Dartium builds) requires a different version of ChromeDriver, that is
@@ -737,7 +804,7 @@
in the default location (inside depot_tools).
"""
current_dir = os.getcwd()
- self.test.test_runner.get_archive('chromedriver')
+ self.test.test_runner.GetArchive('chromedriver')
path = os.environ['PATH'].split(os.pathsep)
orig_chromedriver_path = os.path.join(DART_REPO_LOC, 'tools', 'testing',
'orig-chromedriver')
@@ -748,7 +815,7 @@
if platform.system() == 'Windows':
extension = '.exe'
- def move_chromedriver(depot_tools, copy_to_depot_tools_dir=True,
+ def MoveChromedriver(depot_tools, copy_to_depot_tools_dir=True,
from_path=None):
if from_path:
from_dir = from_path + extension
@@ -770,75 +837,78 @@
if 'depot_tools' in loc:
if browser == 'chrome':
if os.path.exists(orig_chromedriver_path):
- move_chromedriver(loc)
+ MoveChromedriver(loc)
elif browser == 'dartium':
- if self.test.test_runner.current_revision_num < FIRST_CHROMEDRIVER:
+ if (int(self.test.test_runner.current_revision_num) <
+ FIRST_CHROMEDRIVER):
# If we don't have a stashed a different chromedriver just use
# the regular chromedriver.
- self.test.test_runner.run_cmd(os.path.join(
+ self.test.test_runner.RunCmd(os.path.join(
TOP_LEVEL_DIR, 'tools', 'testing', 'webdriver_test_setup.py'),
'-f', '-s', '-p')
elif not os.path.exists(dartium_chromedriver_path):
- self.test.test_runner.get_archive('chromedriver')
+ stdout, _ = self.test.test_runner.GetArchive('chromedriver')
# Move original chromedriver for storage.
if not os.path.exists(orig_chromedriver_path):
- move_chromedriver(loc, copy_to_depot_tools_dir=False)
+ MoveChromedriver(loc, copy_to_depot_tools_dir=False)
if self.test.test_runner.current_revision_num >= FIRST_CHROMEDRIVER:
# Copy Dartium chromedriver into depot_tools
- move_chromedriver(loc, from_path=os.path.join(
+ MoveChromedriver(loc, from_path=os.path.join(
dartium_chromedriver_path, 'chromedriver'))
os.chdir(current_dir)
- def run_tests(self):
+ def RunTests(self):
"""Run dromaeo in the browser."""
- self.test.test_runner.get_archive('dartium')
+ self.test.test_runner.GetArchive('dartium')
# Build tests.
dromaeo_path = os.path.join('samples', 'third_party', 'dromaeo')
current_path = os.getcwd()
os.chdir(dromaeo_path)
- self.test.test_runner.run_cmd(['python', 'generate_dart2js_tests.py'])
+ if os.path.exists('generate_dart2js_tests.py'):
+ stdout, _ = self.test.test_runner.RunCmd(
+ ['python', 'generate_dart2js_tests.py'])
+ else:
+ stdout, _ = self.test.test_runner.RunCmd(
+ ['python', 'generate_frog_tests.py'])
os.chdir(current_path)
+ if 'Error: Compilation failed' in stdout:
+ return
+ versions = DromaeoTester.GetDromaeoVersions()
- versions = DromaeoTester.get_dromaeo_versions()
-
- for browser in BrowserTester.get_browsers():
- self.move_chrome_driver_if_needed(browser)
+ for browser in BrowserTester.GetBrowsers():
+ self.MoveChromeDriverIfNeeded(browser)
for version_name in versions:
- if not self.test.is_valid_combination(browser, version_name):
+ if not self.test.IsValidCombination(browser, version_name):
continue
- version = DromaeoTest.DromaeoPerfTester.get_dromaeo_url_query(
+ version = DromaeoTest.DromaeoPerfTester.GetDromaeoUrlQuery(
browser, version_name)
self.test.trace_file = os.path.join(TOP_LEVEL_DIR,
'tools', 'testing', 'perf_testing', self.test.result_folder_name,
'dromaeo-%s-%s-%s' % (self.test.cur_time, browser, version_name))
- self.add_svn_revision_to_trace(self.test.trace_file, browser)
+ self.AddSvnRevisionToTrace(self.test.trace_file, browser)
file_path = '"%s"' % os.path.join(os.getcwd(), dromaeo_path,
'index-js.html?%s' % version)
- if platform.system() == 'Windows':
- file_path = file_path.replace('&', '^&')
- file_path = file_path.replace('?', '^?')
- file_path = file_path.replace('|', '^|')
- self.test.test_runner.run_cmd(
+ self.test.test_runner.RunCmd(
['python', os.path.join('tools', 'testing', 'run_selenium.py'),
'--out', file_path, '--browser', browser,
'--timeout', '900', '--mode', 'dromaeo'], self.test.trace_file,
append=True)
# Put default Chromedriver back in.
- self.move_chrome_driver_if_needed('chrome')
+ self.MoveChromeDriverIfNeeded('chrome')
@staticmethod
- def get_dromaeo_url_query(browser, version):
+ def GetDromaeoUrlQuery(browser, version):
if browser == 'dartium':
version = version.replace('frog', 'dart')
- version = version.replace('_','&')
- tags = DromaeoTester.get_valid_dromaeo_tags()
- return '|'.join([ '%s&%s' % (version, tag) for tag in tags])
+ version = version.replace('_','AND')
+ tags = DromaeoTester.GetValidDromaeoTags()
+ return 'OR'.join([ '%sAND%s' % (version, tag) for tag in tags])
class DromaeoFileProcessor(Processor):
- def process_file(self, afile, should_post_file):
+ def ProcessFile(self, afile, should_post_file):
"""Comb through the html to find the performance results.
Returns: True if we successfully posted our data to storage."""
parts = afile.split('-')
@@ -847,7 +917,7 @@
bench_dict = self.test.values_dict[browser][version]
- f = self.open_trace_file(afile, should_post_file)
+ f = self.OpenTraceFile(afile, should_post_file)
lines = f.readlines()
i = 0
revision_num = 0
@@ -869,39 +939,40 @@
if results:
for result in results:
r = re.match(result_pattern, result)
- name = DromaeoTester.legalize_filename(r.group(1).strip(':'))
+ name = DromaeoTester.LegalizeFilename(r.group(1).strip(':'))
score = float(r.group(2))
bench_dict[name] += [float(score)]
self.test.revision_dict[browser][version][name] += \
[revision_num]
if not self.test.test_runner.no_upload and should_post_file:
- upload_success = upload_success and self.report_results(
+ upload_success = upload_success and self.ReportResults(
name, score, browser, version, revision_num,
- self.get_score_type(name))
+ self.GetScoreType(name))
else:
upload_success = False
f.close()
- self.calculate_geometric_mean(browser, version, revision_num)
+ self.CalculateGeometricMean(browser, version, revision_num)
return upload_success
class TestBuilder(object):
"""Construct the desired test object."""
- available_suites = dict((suite.name(), suite) for suite in [
+ available_suites = dict((suite.Name(), suite) for suite in [
CommonBrowserTest, DromaeoTest])
@staticmethod
- def make_test(test_name, test_runner):
+ def MakeTest(test_name, test_runner):
return TestBuilder.available_suites[test_name](test_runner)
@staticmethod
- def available_suite_names():
+ def AvailableSuiteNames():
return TestBuilder.available_suites.keys()
-def search_for_revision(directory = None):
+
+def SearchForRevision(directory = None):
"""Find the current revision number in the desired directory. If directory is
None, find the revision number in the current directory."""
- def find_revision(svn_info_command):
+ def FindRevision(svn_info_command):
p = subprocess.Popen(svn_info_command, stdout = subprocess.PIPE,
stderr = subprocess.STDOUT,
shell = (platform.system() == 'Windows'))
@@ -915,13 +986,14 @@
if not directory:
directory = cwd
os.chdir(directory)
- revision_num = int(find_revision(['svn', 'info']))
+ revision_num = int(FindRevision(['svn', 'info']))
if revision_num == -1:
- revision_num = int(find_revision(['git', 'svn', 'info']))
+ revision_num = int(FindRevision(['git', 'svn', 'info']))
os.chdir(cwd)
return str(revision_num)
-def update_set_of_done_cls(revision_num=None):
+
+def UpdateSetOfDoneCls(revision_num=None):
"""Update the set of CLs that do not need additional performance runs.
Args:
revision_num: an additional number to be added to the 'done set'
@@ -941,40 +1013,41 @@
f.close()
return result_set
-def fill_in_back_history(results_set, runner):
+
+def FillInBackHistory(results_set, runner):
"""Fill in back history performance data. This is done one of two ways, with
equal probability of trying each way (falling back on the sequential version
as our data becomes more densely populated)."""
has_run_extra = False
- revision_num = int(search_for_revision(DART_REPO_LOC))
+ revision_num = int(SearchForRevision(DART_REPO_LOC))
- def try_to_run_additional(revision_number):
+ def TryToRunAdditional(revision_number):
"""Determine the number of results we have stored for a particular revision
number, and if it is less than 10, run some extra tests.
Args:
- revision_number: the revision whose performance we want to potentially
test.
Returns: True if we successfully ran some additional tests."""
- if not runner.has_interesting_code(revision_number):
- results_set = update_set_of_done_cls(revision_number)
+ if not runner.HasInterestingCode(revision_number)[0]:
+ results_set = UpdateSetOfDoneCls(revision_number)
return False
- a_test = TestBuilder.make_test(runner.suite_names[0], runner)
+ a_test = TestBuilder.MakeTest(runner.suite_names[0], runner)
benchmark_name = a_test.values_list[0]
platform_name = a_test.platform_list[0]
variant = a_test.values_dict[platform_name].keys()[0]
num_results = post_results.get_num_results(benchmark_name,
platform_name, variant, revision_number,
- a_test.file_processor.get_score_type(benchmark_name))
+ a_test.file_processor.GetScoreType(benchmark_name))
if num_results < 10:
# Run at most two more times.
if num_results > 8:
reruns = 10 - num_results
else:
reruns = 2
- run = runner.run_test_sequence(revision_num=str(revision_number),
+ run = runner.RunTestSequence(revision_num=str(revision_number),
num_reruns=reruns)
if num_results >= 10 or run == 0 and num_results + reruns >= 10:
- results_set = update_set_of_done_cls(revision_number)
+ results_set = UpdateSetOfDoneCls(revision_number)
else:
return False
return True
@@ -993,8 +1066,8 @@
weighted_total = sum(thousands_list)
generated_random_number = random.randint(0, weighted_total - 1)
for i in list(reversed(thousands_list)):
- thousands = thousands_list[i - 1]
- weighted_total -= thousands_list[i - 1]
+ thousands = i
+ weighted_total -= i
if weighted_total <= generated_random_number:
break
while tries < 15 and not has_run_extra:
@@ -1005,7 +1078,7 @@
max_range = bucket_size
rev = thousands * bucket_size + random.randrange(0, max_range)
if rev not in results_set:
- has_run_extra = try_to_run_additional(rev)
+ has_run_extra = TryToRunAdditional(rev)
tries += 1
if not has_run_extra:
@@ -1015,16 +1088,17 @@
# checked in.
while revision_num > EARLIEST_REVISION and not has_run_extra:
if revision_num not in results_set:
- has_run_extra = try_to_run_additional(revision_num)
+ has_run_extra = TryToRunAdditional(revision_num)
revision_num -= 1
if not has_run_extra:
# No more extra back-runs to do (for now). Wait for new code.
time.sleep(200)
return results_set
+
def main():
runner = TestRunner()
- continuous = runner.parse_args()
+ continuous = runner.ParseArgs()
if not os.path.exists(DART_REPO_LOC):
os.mkdir(dirname(DART_REPO_LOC))
@@ -1036,13 +1110,17 @@
p.communicate()
if continuous:
while True:
- results_set = update_set_of_done_cls()
- if runner.has_interesting_code():
- runner.run_test_sequence()
+ results_set = UpdateSetOfDoneCls()
+ (is_interesting, interesting_rev_num) = runner.HasInterestingCode()
+ if is_interesting:
+ runner.RunTestSequence(interesting_rev_num)
else:
- results_set = fill_in_back_history(results_set, runner)
+ if runner.backfill:
+ results_set = FillInBackHistory(results_set, runner)
+ else:
+ time.sleep(200)
else:
- runner.run_test_sequence()
+ runner.RunTestSequence()
if __name__ == '__main__':
main()
« no previous file with comments | « no previous file | tools/testing/webdriver_test_setup.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698