mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-05 03:36:08 +03:00
239 lines
7.0 KiB
Python
239 lines
7.0 KiB
Python
# Copyright 2016 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
import pickle
|
|
import re
|
|
|
|
from devil import base_error
|
|
from devil.utils import cmd_helper
|
|
from pylib import constants
|
|
from pylib.base import base_test_result
|
|
from pylib.base import test_instance
|
|
from pylib.constants import host_paths
|
|
|
|
|
|
_GIT_CR_POS_RE = re.compile(r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$')
|
|
|
|
|
|
def _GetPersistedResult(test_name):
|
|
file_name = os.path.join(constants.PERF_OUTPUT_DIR, test_name)
|
|
if not os.path.exists(file_name):
|
|
logging.error('File not found %s', file_name)
|
|
return None
|
|
|
|
with file(file_name, 'r') as f:
|
|
return pickle.load(f)
|
|
|
|
|
|
def _GetChromiumRevision():
|
|
# pylint: disable=line-too-long
|
|
"""Get the git hash and commit position of the chromium master branch.
|
|
|
|
See:
|
|
https://chromium.googlesource.com/chromium/tools/build/+/387e3cf3/scripts/slave/runtest.py#211
|
|
|
|
Returns:
|
|
A dictionary with 'revision' and 'commit_pos' keys.
|
|
"""
|
|
# pylint: enable=line-too-long
|
|
status, output = cmd_helper.GetCmdStatusAndOutput(
|
|
['git', 'log', '-n', '1', '--pretty=format:%H%n%B', 'HEAD'],
|
|
cwd=host_paths.DIR_SOURCE_ROOT)
|
|
revision = None
|
|
commit_pos = None
|
|
if not status:
|
|
lines = output.splitlines()
|
|
revision = lines[0]
|
|
for line in reversed(lines):
|
|
m = _GIT_CR_POS_RE.match(line.strip())
|
|
if m:
|
|
commit_pos = int(m.group(1))
|
|
break
|
|
return {'revision': revision, 'commit_pos': commit_pos}
|
|
|
|
|
|
class PerfTestInstance(test_instance.TestInstance):
|
|
def __init__(self, args, _):
|
|
super(PerfTestInstance, self).__init__()
|
|
|
|
self._collect_chartjson_data = args.collect_chartjson_data
|
|
self._dry_run = args.dry_run
|
|
self._output_dir_archive_path = args.output_dir_archive_path
|
|
# TODO(rnephew): Get rid of this when everything uses
|
|
# --output-dir-archive-path
|
|
if self._output_dir_archive_path is None and args.get_output_dir_archive:
|
|
self._output_dir_archive_path = args.get_output_dir_archive
|
|
self._known_devices_file = args.known_devices_file
|
|
self._max_battery_temp = args.max_battery_temp
|
|
self._min_battery_level = args.min_battery_level
|
|
self._no_timeout = args.no_timeout
|
|
self._output_chartjson_data = args.output_chartjson_data
|
|
self._output_json_list = args.output_json_list
|
|
self._print_step = args.print_step
|
|
self._single_step = (
|
|
' '.join(args.single_step_command) if args.single_step else None)
|
|
self._steps = args.steps
|
|
self._test_filter = args.test_filter
|
|
self._write_buildbot_json = args.write_buildbot_json
|
|
|
|
#override
|
|
def SetUp(self):
|
|
pass
|
|
|
|
#override
|
|
def TearDown(self):
|
|
pass
|
|
|
|
def OutputJsonList(self):
|
|
try:
|
|
with file(self._steps, 'r') as i:
|
|
all_steps = json.load(i)
|
|
|
|
step_values = []
|
|
for k, v in all_steps['steps'].iteritems():
|
|
data = {'test': k, 'device_affinity': v['device_affinity']}
|
|
|
|
persisted_result = _GetPersistedResult(k)
|
|
if persisted_result:
|
|
data['start_time'] = persisted_result['start_time']
|
|
data['end_time'] = persisted_result['end_time']
|
|
data['total_time'] = persisted_result['total_time']
|
|
data['has_archive'] = persisted_result['archive_bytes'] is not None
|
|
step_values.append(data)
|
|
|
|
with file(self.output_json_list, 'w') as o:
|
|
o.write(json.dumps(step_values))
|
|
return base_test_result.ResultType.PASS
|
|
except KeyError:
|
|
logging.exception('Persistent results file missing key.')
|
|
return base_test_result.ResultType.FAIL
|
|
|
|
def PrintTestOutput(self):
|
|
"""Helper method to print the output of previously executed test_name.
|
|
|
|
Test_name is passed from the command line as print_step
|
|
|
|
Returns:
|
|
exit code generated by the test step.
|
|
"""
|
|
persisted_result = _GetPersistedResult(self._print_step)
|
|
if not persisted_result:
|
|
raise PersistentDataError('No data for test %s found.' % self._print_step)
|
|
logging.info('*' * 80)
|
|
logging.info('Output from:')
|
|
logging.info(persisted_result['cmd'])
|
|
logging.info('*' * 80)
|
|
|
|
output_formatted = ''
|
|
persisted_outputs = persisted_result['output']
|
|
for i in xrange(len(persisted_outputs)):
|
|
output_formatted += '\n\nOutput from run #%d:\n\n%s' % (
|
|
i, persisted_outputs[i])
|
|
print output_formatted
|
|
|
|
if self.output_chartjson_data:
|
|
with file(self.output_chartjson_data, 'w') as f:
|
|
f.write(persisted_result['chartjson'])
|
|
|
|
if self.output_dir_archive_path:
|
|
if persisted_result['archive_bytes'] is not None:
|
|
with file(self.output_dir_archive_path, 'wb') as f:
|
|
f.write(persisted_result['archive_bytes'])
|
|
else:
|
|
logging.error('The output dir was not archived.')
|
|
if persisted_result['exit_code'] == 0:
|
|
return base_test_result.ResultType.PASS
|
|
return base_test_result.ResultType.FAIL
|
|
|
|
#override
|
|
def TestType(self):
|
|
return 'perf'
|
|
|
|
@staticmethod
|
|
def ReadChartjsonOutput(output_dir):
|
|
if not output_dir:
|
|
return ''
|
|
json_output_path = os.path.join(output_dir, 'results-chart.json')
|
|
try:
|
|
with open(json_output_path) as f:
|
|
return f.read()
|
|
except IOError:
|
|
logging.exception('Exception when reading chartjson.')
|
|
logging.error('This usually means that telemetry did not run, so it could'
|
|
' not generate the file. Please check the device running'
|
|
' the test.')
|
|
return ''
|
|
|
|
def WriteBuildBotJson(self, output_dir):
|
|
"""Write metadata about the buildbot environment to the output dir."""
|
|
if not output_dir or not self._write_buildbot_json:
|
|
return
|
|
data = {
|
|
'chromium': _GetChromiumRevision(),
|
|
'environment': dict(os.environ)
|
|
}
|
|
with open(os.path.join(output_dir, 'buildbot.json'), 'w') as f:
|
|
json.dump(data, f, sort_keys=True, separators=(',', ': '))
|
|
|
|
@property
|
|
def collect_chartjson_data(self):
|
|
return self._collect_chartjson_data
|
|
|
|
@property
|
|
def dry_run(self):
|
|
return self._dry_run
|
|
|
|
@property
|
|
def known_devices_file(self):
|
|
return self._known_devices_file
|
|
|
|
@property
|
|
def max_battery_temp(self):
|
|
return self._max_battery_temp
|
|
|
|
@property
|
|
def min_battery_level(self):
|
|
return self._min_battery_level
|
|
|
|
@property
|
|
def no_timeout(self):
|
|
return self._no_timeout
|
|
|
|
@property
|
|
def output_chartjson_data(self):
|
|
return self._output_chartjson_data
|
|
|
|
@property
|
|
def output_dir_archive_path(self):
|
|
return self._output_dir_archive_path
|
|
|
|
@property
|
|
def output_json_list(self):
|
|
return self._output_json_list
|
|
|
|
@property
|
|
def print_step(self):
|
|
return self._print_step
|
|
|
|
@property
|
|
def single_step(self):
|
|
return self._single_step
|
|
|
|
@property
|
|
def steps(self):
|
|
return self._steps
|
|
|
|
@property
|
|
def test_filter(self):
|
|
return self._test_filter
|
|
|
|
|
|
class PersistentDataError(base_error.BaseError):
|
|
def __init__(self, message):
|
|
super(PersistentDataError, self).__init__(message)
|
|
self._is_infra_error = True
|