Reimport
This commit is contained in:
6
tools/adb/systrace/catapult/tracing/tracing/__init__.py
Normal file
6
tools/adb/systrace/catapult/tracing/tracing/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 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 tracing_project
|
||||
tracing_project.UpdateSysPathIfNeeded()
|
||||
@@ -0,0 +1,4 @@
|
||||
# Copyright 2017 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.
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
# Copyright 2014 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.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
import collections
|
||||
import gzip
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import six
|
||||
|
||||
|
||||
try:
|
||||
StringTypes = six.string_types # pylint: disable=invalid-name
|
||||
except NameError:
|
||||
StringTypes = str
|
||||
|
||||
|
||||
_TRACING_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
os.path.pardir, os.path.pardir)
|
||||
_TRACE2HTML_PATH = os.path.join(_TRACING_DIR, 'bin', 'trace2html')
|
||||
|
||||
MIB = 1024 * 1024
|
||||
|
||||
class TraceDataPart(object):
|
||||
"""Trace data can come from a variety of tracing agents.
|
||||
|
||||
Data from each agent is collected into a trace "part" and accessed by the
|
||||
following fixed field names.
|
||||
"""
|
||||
def __init__(self, raw_field_name):
|
||||
self._raw_field_name = raw_field_name
|
||||
|
||||
def __repr__(self):
|
||||
return 'TraceDataPart("%s")' % self._raw_field_name
|
||||
|
||||
@property
|
||||
def raw_field_name(self):
|
||||
return self._raw_field_name
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.raw_field_name == other.raw_field_name
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.raw_field_name)
|
||||
|
||||
|
||||
ANDROID_PROCESS_DATA_PART = TraceDataPart('androidProcessDump')
|
||||
ATRACE_PART = TraceDataPart('systemTraceEvents')
|
||||
ATRACE_PROCESS_DUMP_PART = TraceDataPart('atraceProcessDump')
|
||||
CHROME_TRACE_PART = TraceDataPart('traceEvents')
|
||||
CPU_TRACE_DATA = TraceDataPart('cpuSnapshots')
|
||||
TELEMETRY_PART = TraceDataPart('telemetry')
|
||||
WALT_TRACE_PART = TraceDataPart('waltTraceEvents')
|
||||
|
||||
ALL_TRACE_PARTS = {ANDROID_PROCESS_DATA_PART,
|
||||
ATRACE_PART,
|
||||
ATRACE_PROCESS_DUMP_PART,
|
||||
CHROME_TRACE_PART,
|
||||
CPU_TRACE_DATA,
|
||||
TELEMETRY_PART}
|
||||
|
||||
|
||||
class _TraceData(object):
|
||||
"""Provides read access to traces collected from multiple tracing agents.
|
||||
|
||||
Instances are created by calling the AsData() method on a TraceDataWriter.
|
||||
"""
|
||||
def __init__(self, raw_data):
|
||||
self._raw_data = raw_data
|
||||
|
||||
def HasTracesFor(self, part):
|
||||
return bool(self.GetTracesFor(part))
|
||||
|
||||
def GetTracesFor(self, part):
|
||||
"""Return the list of traces for |part| in string or dictionary forms."""
|
||||
if not isinstance(part, TraceDataPart):
|
||||
raise TypeError('part must be a TraceDataPart instance')
|
||||
return self._raw_data.get(part.raw_field_name, [])
|
||||
|
||||
def GetTraceFor(self, part):
|
||||
traces = self.GetTracesFor(part)
|
||||
assert len(traces) == 1
|
||||
return traces[0]
|
||||
|
||||
|
||||
_TraceItem = collections.namedtuple(
|
||||
'_TraceItem', ['part_name', 'handle', 'compressed'])
|
||||
|
||||
|
||||
class TraceDataBuilder(object):
|
||||
"""TraceDataBuilder helps build up a trace from multiple trace agents.
|
||||
|
||||
Note: the collected trace data is maintained in a set of temporary files to
|
||||
be later processed e.g. by the Serialize() method. To ensure proper clean up
|
||||
of such files clients must call the CleanUpTraceData() method or, even easier,
|
||||
use the context manager API, e.g.:
|
||||
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
builder.AddTraceFor(trace_part, data)
|
||||
builder.Serialize(output_file)
|
||||
"""
|
||||
def __init__(self):
|
||||
self._traces = []
|
||||
self._frozen = False
|
||||
self._temp_dir = tempfile.mkdtemp()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.CleanUpTraceData()
|
||||
|
||||
def OpenTraceHandleFor(self, part, compressed=False):
|
||||
"""Open a file handle for writing trace data into it.
|
||||
|
||||
Args:
|
||||
part: A TraceDataPart instance.
|
||||
compressed: An optional Boolean, indicates whether the written data is
|
||||
gzipped. Note, this information is currently only used by the AsData()
|
||||
method in order to be able to open and read the written data.
|
||||
"""
|
||||
if not isinstance(part, TraceDataPart):
|
||||
raise TypeError('part must be a TraceDataPart instance')
|
||||
if self._frozen:
|
||||
raise RuntimeError('trace data builder is no longer open for writing')
|
||||
trace = _TraceItem(
|
||||
part_name=part.raw_field_name,
|
||||
handle=tempfile.NamedTemporaryFile(delete=False, dir=self._temp_dir),
|
||||
compressed=compressed)
|
||||
self._traces.append(trace)
|
||||
return trace.handle
|
||||
|
||||
def AddTraceFileFor(self, part, trace_file):
|
||||
"""Move a file with trace data into this builder.
|
||||
|
||||
This is useful for situations where a client might want to start collecting
|
||||
trace data into a file, even before the TraceDataBuilder itself is created.
|
||||
|
||||
Args:
|
||||
part: A TraceDataPart instance.
|
||||
trace_file: A path to a file containing trace data. Note: for efficiency
|
||||
the file is moved rather than copied into the builder. Therefore the
|
||||
source file will no longer exist after calling this method; and the
|
||||
lifetime of the trace data will thereafter be managed by this builder.
|
||||
"""
|
||||
with self.OpenTraceHandleFor(part) as handle:
|
||||
pass
|
||||
if os.name == 'nt':
|
||||
# On windows os.rename won't overwrite, so the destination path needs to
|
||||
# be removed first.
|
||||
os.remove(handle.name)
|
||||
os.rename(trace_file, handle.name)
|
||||
|
||||
def AddTraceFor(self, part, data, allow_unstructured=False):
|
||||
"""Record new trace data into this builder.
|
||||
|
||||
Args:
|
||||
part: A TraceDataPart instance.
|
||||
data: The trace data to write: a json-serializable dict, or unstructured
|
||||
text data as a string.
|
||||
allow_unstructured: This must be set to True to allow passing
|
||||
unstructured text data as input. Note: the use of this flag is
|
||||
discouraged and only exists to support legacy clients; new tracing
|
||||
agents should all produce structured trace data (e.g. proto or json).
|
||||
"""
|
||||
if isinstance(data, StringTypes):
|
||||
if not allow_unstructured:
|
||||
raise ValueError('must pass allow_unstructured=True for text data')
|
||||
do_write = lambda d, f: f.write(d)
|
||||
elif isinstance(data, dict):
|
||||
do_write = json.dump
|
||||
else:
|
||||
raise TypeError('invalid trace data type')
|
||||
with self.OpenTraceHandleFor(part) as handle:
|
||||
do_write(data, handle)
|
||||
|
||||
def Freeze(self):
|
||||
"""Do not allow writing any more data into this builder."""
|
||||
self._frozen = True
|
||||
return self
|
||||
|
||||
def CleanUpTraceData(self):
|
||||
"""Clean up resources used by the data builder."""
|
||||
if self._traces is None:
|
||||
return # Already cleaned up.
|
||||
self.Freeze()
|
||||
for trace in self._traces:
|
||||
# Make sure all trace handles are closed. It's fine if we close some
|
||||
# of them multiple times.
|
||||
trace.handle.close()
|
||||
shutil.rmtree(self._temp_dir)
|
||||
self._temp_dir = None
|
||||
self._traces = None
|
||||
|
||||
def Serialize(self, file_path, trace_title=None):
|
||||
"""Serialize the trace data to a file in HTML format."""
|
||||
self.Freeze()
|
||||
assert self._traces, 'trace data has already been cleaned up'
|
||||
|
||||
trace_files = [trace.handle.name for trace in self._traces]
|
||||
SerializeAsHtml(trace_files, file_path, trace_title)
|
||||
|
||||
def AsData(self):
|
||||
"""Allow in-memory access to read the collected JSON trace data.
|
||||
|
||||
This method is only provided for writing tests which require read access
|
||||
to the collected trace data (e.g. for tracing agents to test they correctly
|
||||
write data), and to support legacy TBMv1 metric computation. Only traces
|
||||
in JSON format are supported.
|
||||
|
||||
Be careful: this may require a lot of memory if the traces to process are
|
||||
very large. This has lead in the past to OOM errors (e.g. crbug/672097).
|
||||
|
||||
TODO(crbug/928278): Ideally, this method should be removed when it can be
|
||||
entirely replaced by calls to an external trace processor.
|
||||
"""
|
||||
self.Freeze()
|
||||
assert self._traces, 'trace data has already been cleaned up'
|
||||
|
||||
raw_data = {}
|
||||
for trace in self._traces:
|
||||
traces_for_part = raw_data.setdefault(trace.part_name, [])
|
||||
opener = gzip.open if trace.compressed else open
|
||||
with opener(trace.handle.name, 'rb') as f:
|
||||
traces_for_part.append(json.load(f))
|
||||
return _TraceData(raw_data)
|
||||
|
||||
def IterTraceParts(self):
|
||||
"""Iterates over trace parts.
|
||||
|
||||
Return value: iterator over pairs (part_name, file_path).
|
||||
"""
|
||||
for trace in self._traces:
|
||||
yield trace.part_name, trace.handle.name
|
||||
|
||||
|
||||
def CreateTestTrace(number=1):
|
||||
"""Convenient helper method to create trace data objects for testing.
|
||||
|
||||
Objects are created via the usual trace data writing route, so clients are
|
||||
also responsible for cleaning up trace data themselves.
|
||||
|
||||
Clients are meant to treat these test traces as opaque. No guarantees are
|
||||
made about their contents, which they shouldn't try to read.
|
||||
"""
|
||||
builder = TraceDataBuilder()
|
||||
builder.AddTraceFor(CHROME_TRACE_PART, {'traceEvents': [{'test': number}]})
|
||||
return builder.Freeze()
|
||||
|
||||
|
||||
def CreateFromRawChromeEvents(events):
|
||||
"""Convenient helper to create trace data objects from raw Chrome events.
|
||||
|
||||
This bypasses trace data writing, going directly to the in-memory json trace
|
||||
representation, so there is no need for trace file cleanup.
|
||||
|
||||
This is used only for testing legacy clients that still read trace data.
|
||||
"""
|
||||
assert isinstance(events, list)
|
||||
return _TraceData({
|
||||
CHROME_TRACE_PART.raw_field_name: [{'traceEvents': events}]})
|
||||
|
||||
|
||||
def SerializeAsHtml(trace_files, html_file, trace_title=None):
|
||||
"""Serialize a set of traces to a single file in HTML format.
|
||||
|
||||
Args:
|
||||
trace_files: a list of file names, each containing a trace from
|
||||
one of the tracing agents.
|
||||
html_file: a name of the output file.
|
||||
trace_title: optional. A title for the resulting trace.
|
||||
"""
|
||||
if not trace_files:
|
||||
raise ValueError('trace files list is empty')
|
||||
|
||||
input_size = sum(os.path.getsize(trace_file) for trace_file in trace_files)
|
||||
|
||||
cmd = ['python', _TRACE2HTML_PATH]
|
||||
cmd.extend(trace_files)
|
||||
cmd.extend(['--output', html_file])
|
||||
if trace_title is not None:
|
||||
cmd.extend(['--title', trace_title])
|
||||
|
||||
start_time = time.time()
|
||||
subprocess.check_output(cmd)
|
||||
elapsed_time = time.time() - start_time
|
||||
logging.info('trace2html processed %.01f MiB of trace data in %.02f seconds.',
|
||||
1.0 * input_size / MIB, elapsed_time)
|
||||
@@ -0,0 +1,114 @@
|
||||
# Copyright 2014 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 base64
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from py_utils import tempfile_ext
|
||||
from tracing.trace_data import trace_data
|
||||
|
||||
|
||||
class TraceDataTest(unittest.TestCase):
|
||||
def testHasTracesForChrome(self):
|
||||
d = trace_data.CreateFromRawChromeEvents([{'ph': 'B'}])
|
||||
self.assertTrue(d.HasTracesFor(trace_data.CHROME_TRACE_PART))
|
||||
|
||||
def testHasNotTracesForCpu(self):
|
||||
d = trace_data.CreateFromRawChromeEvents([{'ph': 'B'}])
|
||||
self.assertFalse(d.HasTracesFor(trace_data.CPU_TRACE_DATA))
|
||||
|
||||
def testGetTracesForChrome(self):
|
||||
d = trace_data.CreateFromRawChromeEvents([{'ph': 'B'}])
|
||||
ts = d.GetTracesFor(trace_data.CHROME_TRACE_PART)
|
||||
self.assertEqual(len(ts), 1)
|
||||
self.assertEqual(ts[0], {'traceEvents': [{'ph': 'B'}]})
|
||||
|
||||
def testGetNoTracesForCpu(self):
|
||||
d = trace_data.CreateFromRawChromeEvents([{'ph': 'B'}])
|
||||
ts = d.GetTracesFor(trace_data.CPU_TRACE_DATA)
|
||||
self.assertEqual(ts, [])
|
||||
|
||||
|
||||
class TraceDataBuilderTest(unittest.TestCase):
|
||||
def testAddTraceDataAndSerialize(self):
|
||||
with tempfile_ext.TemporaryFileName() as trace_path:
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
builder.AddTraceFor(trace_data.CHROME_TRACE_PART,
|
||||
{'traceEvents': [1, 2, 3]})
|
||||
builder.Serialize(trace_path)
|
||||
self.assertTrue(os.path.exists(trace_path))
|
||||
self.assertGreater(os.stat(trace_path).st_size, 0) # File not empty.
|
||||
|
||||
def testAddTraceForRaisesWithInvalidPart(self):
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
with self.assertRaises(TypeError):
|
||||
builder.AddTraceFor('not_a_trace_part', {})
|
||||
|
||||
def testAddTraceWithUnstructuredData(self):
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
builder.AddTraceFor(trace_data.TELEMETRY_PART, 'unstructured trace',
|
||||
allow_unstructured=True)
|
||||
|
||||
def testAddTraceRaisesWithImplicitUnstructuredData(self):
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
with self.assertRaises(ValueError):
|
||||
builder.AddTraceFor(trace_data.TELEMETRY_PART, 'unstructured trace')
|
||||
|
||||
def testAddTraceFileFor(self):
|
||||
original_data = {'msg': 'The answer is 42'}
|
||||
with tempfile.NamedTemporaryFile(delete=False) as source:
|
||||
json.dump(original_data, source)
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
builder.AddTraceFileFor(trace_data.CHROME_TRACE_PART, source.name)
|
||||
self.assertFalse(os.path.exists(source.name))
|
||||
out_data = builder.AsData().GetTraceFor(trace_data.CHROME_TRACE_PART)
|
||||
|
||||
self.assertEqual(original_data, out_data)
|
||||
|
||||
def testOpenTraceHandleFor(self):
|
||||
original_data = {'msg': 'The answer is 42'}
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
with builder.OpenTraceHandleFor(trace_data.CHROME_TRACE_PART) as handle:
|
||||
handle.write(json.dumps(original_data))
|
||||
out_data = builder.AsData().GetTraceFor(trace_data.CHROME_TRACE_PART)
|
||||
|
||||
# Trace handle should be cleaned up.
|
||||
self.assertFalse(os.path.exists(handle.name))
|
||||
self.assertEqual(original_data, out_data)
|
||||
|
||||
def testOpenTraceHandleForCompressedData(self):
|
||||
original_data = {'msg': 'The answer is 42'}
|
||||
# gzip.compress() does not work in python 2, so hardcode the encoded data.
|
||||
compressed_data = base64.b64decode(
|
||||
'H4sIAIDMblwAA6tWyi1OV7JSUArJSFVIzCsuTy1SyCxWMDFSquUCAA4QMtscAAAA')
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
with builder.OpenTraceHandleFor(
|
||||
trace_data.CHROME_TRACE_PART, compressed=True) as handle:
|
||||
handle.write(compressed_data)
|
||||
out_data = builder.AsData().GetTraceFor(trace_data.CHROME_TRACE_PART)
|
||||
|
||||
# Trace handle should be cleaned up.
|
||||
self.assertFalse(os.path.exists(handle.name))
|
||||
self.assertEqual(original_data, out_data)
|
||||
|
||||
def testCantWriteAfterCleanup(self):
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
builder.AddTraceFor(trace_data.CHROME_TRACE_PART,
|
||||
{'traceEvents': [1, 2, 3]})
|
||||
builder.CleanUpTraceData()
|
||||
with self.assertRaises(RuntimeError):
|
||||
builder.AddTraceFor(trace_data.CHROME_TRACE_PART,
|
||||
{'traceEvents': [1, 2, 3]})
|
||||
|
||||
def testCantWriteAfterFreeze(self):
|
||||
with trace_data.TraceDataBuilder() as builder:
|
||||
builder.AddTraceFor(trace_data.CHROME_TRACE_PART,
|
||||
{'traceEvents': [1, 2, 3]})
|
||||
builder.Freeze()
|
||||
with self.assertRaises(RuntimeError):
|
||||
builder.AddTraceFor(trace_data.CHROME_TRACE_PART,
|
||||
{'traceEvents': [1, 2, 3]})
|
||||
211
tools/adb/systrace/catapult/tracing/tracing_project.py
Normal file
211
tools/adb/systrace/catapult/tracing/tracing_project.py
Normal file
@@ -0,0 +1,211 @@
|
||||
# Copyright (c) 2014 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 sys
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
def _AddToPathIfNeeded(path):
|
||||
if path not in sys.path:
|
||||
sys.path.insert(0, path)
|
||||
|
||||
|
||||
def UpdateSysPathIfNeeded():
|
||||
for path in GetDependencyPaths():
|
||||
_AddToPathIfNeeded(path)
|
||||
|
||||
|
||||
def GetDependencyPaths():
|
||||
# TODO(#3703): Separate the paths that are only used by the dev server into
|
||||
# another call.
|
||||
p = TracingProject()
|
||||
return [
|
||||
p.catapult_path,
|
||||
p.py_vulcanize_path,
|
||||
p.vinn_path,
|
||||
os.path.join(p.catapult_third_party_path, 'WebOb'),
|
||||
os.path.join(p.catapult_third_party_path, 'Paste'),
|
||||
os.path.join(p.catapult_third_party_path, 'six'),
|
||||
os.path.join(p.catapult_third_party_path, 'webapp2'),
|
||||
os.path.join(p.catapult_path, 'common', 'py_utils'),
|
||||
os.path.join(p.tracing_third_party_path, 'symbols')
|
||||
]
|
||||
|
||||
|
||||
def _FindAllFilesRecursive(source_paths):
|
||||
assert isinstance(source_paths, list)
|
||||
all_filenames = set()
|
||||
for source_path in source_paths:
|
||||
for dirpath, _, filenames in os.walk(source_path):
|
||||
for f in filenames:
|
||||
if f.startswith('.'):
|
||||
continue
|
||||
x = os.path.abspath(os.path.join(dirpath, f))
|
||||
all_filenames.add(x)
|
||||
return all_filenames
|
||||
|
||||
def _IsFilenameATest(x):
|
||||
if x.endswith('_test.js'):
|
||||
return True
|
||||
|
||||
if x.endswith('_test.html'):
|
||||
return True
|
||||
|
||||
if x.endswith('_unittest.js'):
|
||||
return True
|
||||
|
||||
if x.endswith('_unittest.html'):
|
||||
return True
|
||||
|
||||
# TODO(nduca): Add content test?
|
||||
return False
|
||||
|
||||
|
||||
class TracingProject(object):
|
||||
catapult_path = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), os.path.pardir))
|
||||
|
||||
tracing_root_path = os.path.join(catapult_path, 'tracing')
|
||||
trace_processor_root_path = os.path.join(catapult_path, 'trace_processor')
|
||||
common_root_path = os.path.join(catapult_path, 'common')
|
||||
tracing_src_path = os.path.join(tracing_root_path, 'tracing')
|
||||
extras_path = os.path.join(tracing_src_path, 'extras')
|
||||
ui_extras_path = os.path.join(tracing_src_path, 'ui', 'extras')
|
||||
|
||||
catapult_third_party_path = os.path.join(catapult_path, 'third_party')
|
||||
polymer_path = os.path.join(catapult_third_party_path, 'polymer')
|
||||
|
||||
tracing_third_party_path = os.path.join(tracing_root_path, 'third_party')
|
||||
py_vulcanize_path = os.path.join(common_root_path, 'py_vulcanize')
|
||||
vinn_path = os.path.join(catapult_third_party_path, 'vinn')
|
||||
|
||||
jszip_path = os.path.join(tracing_third_party_path, 'jszip')
|
||||
pako_path = os.path.join(tracing_third_party_path, 'pako')
|
||||
jpegjs_path = os.path.join(tracing_third_party_path, 'jpeg-js')
|
||||
|
||||
glmatrix_path = os.path.join(
|
||||
tracing_third_party_path, 'gl-matrix', 'dist')
|
||||
|
||||
mannwhitneyu_path = os.path.join(
|
||||
tracing_third_party_path, 'mannwhitneyu')
|
||||
|
||||
ui_path = os.path.join(tracing_src_path, 'ui')
|
||||
d3_path = os.path.join(tracing_third_party_path, 'd3')
|
||||
chai_path = os.path.join(tracing_third_party_path, 'chai')
|
||||
mocha_path = os.path.join(tracing_third_party_path, 'mocha')
|
||||
oboe_path = os.path.join(tracing_third_party_path, 'oboe')
|
||||
|
||||
mre_path = os.path.join(tracing_src_path, 'mre')
|
||||
|
||||
metrics_path = os.path.join(tracing_src_path, 'metrics')
|
||||
diagnostics_path = os.path.join(tracing_src_path, 'value', 'diagnostics')
|
||||
|
||||
value_ui_path = os.path.join(tracing_src_path, 'value', 'ui')
|
||||
metrics_ui_path = os.path.join(tracing_src_path, 'metrics', 'ui')
|
||||
|
||||
test_data_path = os.path.join(tracing_root_path, 'test_data')
|
||||
skp_data_path = os.path.join(tracing_root_path, 'skp_data')
|
||||
|
||||
rjsmin_path = os.path.join(
|
||||
tracing_third_party_path, 'tvcm', 'third_party', 'rjsmin')
|
||||
rcssmin_path = os.path.join(
|
||||
tracing_third_party_path, 'tvcm', 'third_party', 'rcssmin')
|
||||
|
||||
def __init__(self):
|
||||
self.source_paths = []
|
||||
self.source_paths.append(self.tracing_root_path)
|
||||
self.source_paths.append(self.polymer_path)
|
||||
self.source_paths.append(self.tracing_third_party_path)
|
||||
self.source_paths.append(self.mre_path)
|
||||
self.source_paths.append(self.jszip_path)
|
||||
self.source_paths.append(self.pako_path)
|
||||
self.source_paths.append(self.jpegjs_path)
|
||||
self.source_paths.append(self.glmatrix_path)
|
||||
self.source_paths.append(self.mannwhitneyu_path)
|
||||
self.source_paths.append(self.d3_path)
|
||||
self.source_paths.append(self.chai_path)
|
||||
self.source_paths.append(self.mocha_path)
|
||||
self.source_paths.append(self.oboe_path)
|
||||
|
||||
def CreateVulcanizer(self):
|
||||
from py_vulcanize import project as project_module
|
||||
return project_module.Project(self.source_paths)
|
||||
|
||||
def IsD8CompatibleFile(self, filename):
|
||||
if filename.startswith(self.ui_path):
|
||||
return False
|
||||
|
||||
if filename.startswith(self.value_ui_path):
|
||||
return False
|
||||
|
||||
if filename.startswith(self.metrics_ui_path):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def FindAllTestModuleRelPaths(self, pred=None):
|
||||
if pred is None:
|
||||
pred = lambda x: True
|
||||
|
||||
all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
|
||||
test_module_filenames = [x for x in all_filenames if
|
||||
_IsFilenameATest(x) and pred(x)]
|
||||
test_module_filenames.sort()
|
||||
|
||||
return [os.path.relpath(x, self.tracing_root_path)
|
||||
for x in test_module_filenames]
|
||||
|
||||
def FindAllMetricsModuleRelPaths(self):
|
||||
all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
|
||||
all_metrics_module_filenames = []
|
||||
for x in all_filenames:
|
||||
if x.startswith(self.metrics_path) and not _IsFilenameATest(x):
|
||||
all_metrics_module_filenames.append(x)
|
||||
all_metrics_module_filenames.sort()
|
||||
return [os.path.relpath(x, self.tracing_root_path)
|
||||
for x in all_metrics_module_filenames]
|
||||
|
||||
def FindAllDiagnosticsModuleRelPaths(self):
|
||||
all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
|
||||
all_diagnostics_module_filenames = []
|
||||
for x in all_filenames:
|
||||
if x.startswith(self.diagnostics_path) and not _IsFilenameATest(x):
|
||||
all_diagnostics_module_filenames.append(x)
|
||||
all_diagnostics_module_filenames.sort()
|
||||
return [os.path.relpath(x, self.tracing_root_path)
|
||||
for x in all_diagnostics_module_filenames]
|
||||
|
||||
def FindAllD8TestModuleRelPaths(self):
|
||||
return self.FindAllTestModuleRelPaths(pred=self.IsD8CompatibleFile)
|
||||
|
||||
def GetConfigNames(self):
|
||||
config_files = [
|
||||
os.path.join(self.ui_extras_path, x)
|
||||
for x in os.listdir(self.ui_extras_path)
|
||||
if x.endswith('_config.html')
|
||||
]
|
||||
|
||||
config_files = [x for x in config_files if os.path.isfile(x)]
|
||||
|
||||
config_basenames = [os.path.basename(x) for x in config_files]
|
||||
config_names = [re.match('(.+)_config.html$', x).group(1)
|
||||
for x in config_basenames]
|
||||
return config_names
|
||||
|
||||
def GetDefaultConfigName(self):
|
||||
assert 'full' in self.GetConfigNames()
|
||||
return 'full'
|
||||
|
||||
def AddConfigNameOptionToParser(self, parser):
|
||||
choices = self.GetConfigNames()
|
||||
parser.add_argument(
|
||||
'--config', dest='config_name',
|
||||
choices=choices, default=self.GetDefaultConfigName(),
|
||||
help='Picks a browser config. Valid choices: %s' % ', '.join(choices))
|
||||
return choices
|
||||
|
||||
def GetModuleNameForConfigName(self, config_name):
|
||||
return 'tracing.ui.extras.%s_config' % config_name
|
||||
|
||||
Reference in New Issue
Block a user