aboutsummaryrefslogtreecommitdiff
path: root/catapult/systrace/profile_chrome
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/systrace/profile_chrome')
-rw-r--r--catapult/systrace/profile_chrome/agents_unittest.py29
-rw-r--r--catapult/systrace/profile_chrome/atrace_tracing_agent.py51
-rw-r--r--catapult/systrace/profile_chrome/atrace_tracing_agent_unittest.py12
-rw-r--r--catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py37
-rw-r--r--catapult/systrace/profile_chrome/chrome_startup_tracing_agent_unittest.py8
-rw-r--r--catapult/systrace/profile_chrome/chrome_tracing_agent.py98
-rw-r--r--catapult/systrace/profile_chrome/chrome_tracing_agent_unittest.py25
-rw-r--r--catapult/systrace/profile_chrome/ddms_tracing_agent.py29
-rw-r--r--catapult/systrace/profile_chrome/ddms_tracing_agent_unittest.py7
-rw-r--r--catapult/systrace/profile_chrome/fake_agent_1.py69
-rw-r--r--catapult/systrace/profile_chrome/fake_agent_2.py68
-rw-r--r--catapult/systrace/profile_chrome/flags.py18
-rwxr-xr-xcatapult/systrace/profile_chrome/main.py170
-rw-r--r--catapult/systrace/profile_chrome/perf_tracing_agent.py53
-rw-r--r--catapult/systrace/profile_chrome/perf_tracing_agent_unittest.py13
-rw-r--r--catapult/systrace/profile_chrome/profiler.py59
-rw-r--r--catapult/systrace/profile_chrome/profiler_unittest.py68
17 files changed, 558 insertions, 256 deletions
diff --git a/catapult/systrace/profile_chrome/agents_unittest.py b/catapult/systrace/profile_chrome/agents_unittest.py
index 527162cf..8a223819 100644
--- a/catapult/systrace/profile_chrome/agents_unittest.py
+++ b/catapult/systrace/profile_chrome/agents_unittest.py
@@ -8,6 +8,7 @@ from profile_chrome import profiler
from devil.android import device_utils
from devil.android.sdk import intent
+from devil.android.sdk import keyevent
class BaseAgentTest(unittest.TestCase):
@@ -17,8 +18,28 @@ class BaseAgentTest(unittest.TestCase):
self.package_info = profiler.GetSupportedBrowsers()[self.browser]
self.device = devices[0]
- self.device.ForceStop(self.package_info.package)
+ curr_browser = self.GetChromeProcessID()
+ if curr_browser == None:
+ self.StartBrowser()
+
+ def StartBrowser(self):
+ # Turn on the device screen.
+ self.device.SetScreen(True)
+
+ # Unlock device.
+ self.device.SendKeyEvent(keyevent.KEYCODE_MENU)
+
+ # Start browser.
self.device.StartActivity(
- intent.Intent(activity=self.package_info.activity,
- package=self.package_info.package),
- blocking=True)
+ intent.Intent(activity=self.package_info.activity,
+ package=self.package_info.package,
+ data='about:blank',
+ extras={'create_new_tab': True}),
+ blocking=True, force_stop=True)
+
+ def GetChromeProcessID(self):
+ chrome_processes = self.device.GetPids(self.package_info.package)
+ if (self.package_info.package in chrome_processes and
+ len(chrome_processes[self.package_info.package]) > 0):
+ return chrome_processes[self.package_info.package][0]
+ return None
diff --git a/catapult/systrace/profile_chrome/atrace_tracing_agent.py b/catapult/systrace/profile_chrome/atrace_tracing_agent.py
index c9ce8e44..c98906f0 100644
--- a/catapult/systrace/profile_chrome/atrace_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/atrace_tracing_agent.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import optparse
import py_utils
import threading
import zlib
@@ -22,18 +23,22 @@ _ATRACE_OPTIONS = [
# Interval in seconds for sampling atrace data.
_ATRACE_INTERVAL = 15
+# If a custom list of categories is not specified, traces will include
+# these categories (if available on the device).
+_DEFAULT_CATEGORIES = 'sched gfx view dalvik webview input disk am wm'.split()
+
_TRACING_ON_PATH = '/sys/kernel/debug/tracing/tracing_on'
class AtraceAgent(tracing_agents.TracingAgent):
- def __init__(self, device, categories, ring_buffer):
+ def __init__(self, device, ring_buffer):
tracing_agents.TracingAgent.__init__(self)
self._device = device
- self._categories = categories
self._ring_buffer = ring_buffer
self._done = threading.Event()
self._thread = None
self._trace_data = None
+ self._categories = None
def __repr__(self):
return 'atrace'
@@ -43,13 +48,16 @@ class AtraceAgent(tracing_agents.TracingAgent):
return device.RunShellCommand('atrace --list_categories')
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
- def StartAgentTracing(self, options, categories, timeout=None):
+ def StartAgentTracing(self, config, timeout=None):
+ self._categories = _ComputeAtraceCategories(config)
self._thread = threading.Thread(target=self._CollectData)
self._thread.start()
+ return True
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
def StopAgentTracing(self, timeout=None):
self._done.set()
+ return True
@py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
def GetResults(self, timeout=None):
@@ -61,6 +69,7 @@ class AtraceAgent(tracing_agents.TracingAgent):
return False
def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ # pylint: disable=unused-argument
assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
'recorded since explicit clock sync is not supported.')
@@ -117,3 +126,39 @@ class AtraceAgent(tracing_agents.TracingAgent):
# Skip the initial newline.
return trace_data[1:]
+
+
+class AtraceConfig(tracing_agents.TracingConfig):
+ def __init__(self, atrace_categories, device, ring_buffer):
+ tracing_agents.TracingConfig.__init__(self)
+ self.atrace_categories = atrace_categories
+ self.device = device
+ self.ring_buffer = ring_buffer
+
+
+def try_create_agent(config):
+ if config.atrace_categories:
+ return AtraceAgent(config.device, config.ring_buffer)
+ return None
+
+def add_options(parser):
+ atrace_opts = optparse.OptionGroup(parser, 'Atrace tracing options')
+ atrace_opts.add_option('-s', '--systrace', help='Capture a systrace with '
+ 'the chosen comma-delimited systrace categories. You'
+ ' can also capture a combined Chrome + systrace by '
+ 'enabling both types of categories. Use "list" to '
+ 'see the available categories. Systrace is disabled'
+ ' by default. Note that in this case, Systrace is '
+ 'synonymous with Atrace.',
+ metavar='ATRACE_CATEGORIES',
+ dest='atrace_categories', default='')
+ return atrace_opts
+
+def get_config(options):
+ return AtraceConfig(options.atrace_categories, options.device,
+ options.ring_buffer)
+
+def _ComputeAtraceCategories(config):
+ if not config.atrace_categories:
+ return _DEFAULT_CATEGORIES
+ return config.atrace_categories.split(',')
diff --git a/catapult/systrace/profile_chrome/atrace_tracing_agent_unittest.py b/catapult/systrace/profile_chrome/atrace_tracing_agent_unittest.py
index 8460e9b4..24f3c7e3 100644
--- a/catapult/systrace/profile_chrome/atrace_tracing_agent_unittest.py
+++ b/catapult/systrace/profile_chrome/atrace_tracing_agent_unittest.py
@@ -4,24 +4,30 @@
from profile_chrome import agents_unittest
from profile_chrome import atrace_tracing_agent
+from systrace import decorators
class AtraceAgentTest(agents_unittest.BaseAgentTest):
+ @decorators.ClientOnlyTest
def testGetCategories(self):
categories = \
atrace_tracing_agent.AtraceAgent.GetCategories(self.device)
self.assertTrue(categories)
assert 'gfx' in ' '.join(categories)
+ # TODO(washingtonp): This test throws an error on the Trybot servers when
+ # running profile_chrome's atrace agent. Once systrace uses profile_chrome's
+ # agent instead, this test may not longer need to be disabled.
+ @decorators.Disabled
def testTracing(self):
- categories = ['gfx', 'input', 'view']
+ categories = 'gfx,input,view'
ring_buffer = False
agent = atrace_tracing_agent.AtraceAgent(self.device,
- categories,
ring_buffer)
try:
- agent.StartAgentTracing(None, None)
+ agent.StartAgentTracing(atrace_tracing_agent.AtraceConfig(categories,
+ self.device, ring_buffer))
finally:
agent.StopAgentTracing()
result = agent.GetResults()
diff --git a/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py b/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py
index a7693007..a133a465 100644
--- a/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/chrome_startup_tracing_agent.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import optparse
import os
import py_utils
import re
@@ -56,9 +57,10 @@ class ChromeStartupTracingAgent(tracing_agents.TracingAgent):
self._flag_changer.Restore()
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
- def StartAgentTracing(self, options, categories, timeout=None):
+ def StartAgentTracing(self, config, timeout=None):
self._SetupTracing()
self._logcat_monitor.Start()
+ return True
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
def StopAgentTracing(self, timeout=None):
@@ -67,6 +69,7 @@ class ChromeStartupTracingAgent(tracing_agents.TracingAgent):
self._trace_finish_re).group(1)
finally:
self._TearDownTracing()
+ return True
@py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
def GetResults(self, timeout=None):
@@ -84,5 +87,37 @@ class ChromeStartupTracingAgent(tracing_agents.TracingAgent):
return False
def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ # pylint: disable=unused-argument
assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
'recorded since explicit clock sync is not supported.')
+
+
+class ChromeStartupConfig(tracing_agents.TracingConfig):
+ def __init__(self, device, package_info, cold, url, chrome_categories):
+ tracing_agents.TracingConfig.__init__(self)
+ self.device = device
+ self.package_info = package_info
+ self.cold = cold
+ self.url = url
+ self.chrome_categories = chrome_categories
+
+
+def try_create_agent(config):
+ return ChromeStartupTracingAgent(config.device, config.package_info,
+ config.cold, config.url)
+
+def add_options(parser):
+ options = optparse.OptionGroup(parser, 'Chrome startup tracing')
+ options.add_option('--url', help='URL to visit on startup. Default: '
+ 'https://www.google.com. An empty URL launches Chrome '
+ 'with a MAIN action instead of VIEW.',
+ default='https://www.google.com', metavar='URL')
+ options.add_option('--cold', help='Flush the OS page cache before starting '
+ 'the browser. Note that this require a device with root '
+ 'access.', default=False, action='store_true')
+ return options
+
+def get_config(options):
+ return ChromeStartupConfig(options.device, options.package_info,
+ options.cold, options.url,
+ options.chrome_categories)
diff --git a/catapult/systrace/profile_chrome/chrome_startup_tracing_agent_unittest.py b/catapult/systrace/profile_chrome/chrome_startup_tracing_agent_unittest.py
index 6c83c74a..85732da8 100644
--- a/catapult/systrace/profile_chrome/chrome_startup_tracing_agent_unittest.py
+++ b/catapult/systrace/profile_chrome/chrome_startup_tracing_agent_unittest.py
@@ -6,15 +6,21 @@ import json
from profile_chrome import chrome_startup_tracing_agent
from profile_chrome import agents_unittest
+from systrace import decorators
class ChromeAgentTest(agents_unittest.BaseAgentTest):
+ # TODO(washingtonp): This test seems to fail on the version of Android
+ # currently on the Trybot servers (KTU84P), although it works on Android M.
+ # Either upgrade the version of Android on the Trybot servers or determine
+ # if there is a way to run this agent on Android KTU84P.
+ @decorators.Disabled
def testTracing(self):
agent = chrome_startup_tracing_agent.ChromeStartupTracingAgent(
self.device, self.package_info, False, 'https://www.google.com')
try:
- agent.StartAgentTracing(None, None)
+ agent.StartAgentTracing(None)
finally:
agent.StopAgentTracing()
diff --git a/catapult/systrace/profile_chrome/chrome_tracing_agent.py b/catapult/systrace/profile_chrome/chrome_tracing_agent.py
index b13f5ea2..656a559d 100644
--- a/catapult/systrace/profile_chrome/chrome_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/chrome_tracing_agent.py
@@ -3,27 +3,26 @@
# found in the LICENSE file.
import json
+import optparse
import os
import py_utils
import re
from devil.android import device_errors
from devil.android.sdk import intent
-
from systrace import trace_result
from systrace import tracing_agents
+_DEFAULT_CHROME_CATEGORIES = '_DEFAULT_CHROME_CATEGORIES'
_HEAP_PROFILE_MMAP_PROPERTY = 'heapprof.mmap'
class ChromeTracingAgent(tracing_agents.TracingAgent):
- def __init__(self, device, package_info,
- categories, ring_buffer, trace_memory=False):
+ def __init__(self, device, package_info, ring_buffer, trace_memory=False):
tracing_agents.TracingAgent.__init__(self)
self._device = device
self._package_info = package_info
- self._categories = categories
self._ring_buffer = ring_buffer
self._logcat_monitor = self._device.GetLogcatMonitor()
self._trace_file = None
@@ -33,6 +32,7 @@ class ChromeTracingAgent(tracing_agents.TracingAgent):
re.compile(r'Logging performance trace to file')
self._trace_finish_re = \
re.compile(r'Profiler finished[.] Results are in (.*)[.]')
+ self._categories = None
def __repr__(self):
return 'chrome trace'
@@ -62,7 +62,8 @@ class ChromeTracingAgent(tracing_agents.TracingAgent):
return list(record_categories), list(disabled_by_default_categories)
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
- def StartAgentTracing(self, options, categories, timeout=None):
+ def StartAgentTracing(self, config, timeout=None):
+ self._categories = _ComputeChromeCategories(config)
self._logcat_monitor.Start()
start_extras = {'categories': ','.join(self._categories)}
if self._ring_buffer:
@@ -89,6 +90,7 @@ class ChromeTracingAgent(tracing_agents.TracingAgent):
raise RuntimeError(
'Trace start marker not found. Possible causes: 1) Is the correct '
'version of the browser running? 2) Is the browser already launched?')
+ return True
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
def StopAgentTracing(self, timeout=None):
@@ -100,6 +102,7 @@ class ChromeTracingAgent(tracing_agents.TracingAgent):
self._is_tracing = False
if self._trace_memory:
self._device.SetProp(_HEAP_PROFILE_MMAP_PROPERTY, 0)
+ return True
@py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
def GetResults(self, timeout=None):
@@ -123,5 +126,90 @@ class ChromeTracingAgent(tracing_agents.TracingAgent):
return False
def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ # pylint: disable=unused-argument
assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
'recorded since explicit clock sync is not supported.')
+
+
+class ChromeConfig(tracing_agents.TracingConfig):
+ def __init__(self, chrome_categories, trace_cc, trace_frame_viewer,
+ trace_ubercompositor, trace_gpu, trace_flow, trace_memory,
+ trace_scheduler, ring_buffer, device, package_info):
+ tracing_agents.TracingConfig.__init__(self)
+ self.chrome_categories = chrome_categories
+ self.trace_cc = trace_cc
+ self.trace_frame_viewer = trace_frame_viewer
+ self.trace_ubercompositor = trace_ubercompositor
+ self.trace_gpu = trace_gpu
+ self.trace_flow = trace_flow
+ self.trace_memory = trace_memory
+ self.trace_scheduler = trace_scheduler
+ self.ring_buffer = ring_buffer
+ self.device = device
+ self.package_info = package_info
+
+
+def try_create_agent(config):
+ if config.chrome_categories:
+ return ChromeTracingAgent(config.device, config.package_info,
+ config.ring_buffer, config.trace_memory)
+ return None
+
+def add_options(parser):
+ chrome_opts = optparse.OptionGroup(parser, 'Chrome tracing options')
+ chrome_opts.add_option('-c', '--categories', help='Select Chrome tracing '
+ 'categories with comma-delimited wildcards, '
+ 'e.g., "*", "cat1*,-cat1a". Omit this option to trace '
+ 'Chrome\'s default categories. Chrome tracing can be '
+ 'disabled with "--categories=\'\'". Use "list" to '
+ 'see the available categories.',
+ metavar='CHROME_CATEGORIES', dest='chrome_categories',
+ default=_DEFAULT_CHROME_CATEGORIES)
+ chrome_opts.add_option('--trace-cc',
+ help='Deprecated, use --trace-frame-viewer.',
+ action='store_true')
+ chrome_opts.add_option('--trace-frame-viewer',
+ help='Enable enough trace categories for '
+ 'compositor frame viewing.', action='store_true')
+ chrome_opts.add_option('--trace-ubercompositor',
+ help='Enable enough trace categories for '
+ 'ubercompositor frame data.', action='store_true')
+ chrome_opts.add_option('--trace-gpu', help='Enable extra trace categories '
+ 'for GPU data.', action='store_true')
+ chrome_opts.add_option('--trace-flow', help='Enable extra trace categories '
+ 'for IPC message flows.', action='store_true')
+ chrome_opts.add_option('--trace-memory', help='Enable extra trace categories '
+ 'for memory profile. (tcmalloc required)',
+ action='store_true')
+ chrome_opts.add_option('--trace-scheduler', help='Enable extra trace '
+ 'categories for scheduler state',
+ action='store_true')
+ return chrome_opts
+
+def get_config(options):
+ return ChromeConfig(options.chrome_categories, options.trace_cc,
+ options.trace_frame_viewer, options.trace_ubercompositor,
+ options.trace_gpu, options.trace_flow,
+ options.trace_memory, options.trace_scheduler,
+ options.ring_buffer, options.device,
+ options.package_info)
+
+def _ComputeChromeCategories(config):
+ categories = []
+ if config.trace_frame_viewer:
+ categories.append('disabled-by-default-cc.debug')
+ if config.trace_ubercompositor:
+ categories.append('disabled-by-default-cc.debug*')
+ if config.trace_gpu:
+ categories.append('disabled-by-default-gpu.debug*')
+ if config.trace_flow:
+ categories.append('disabled-by-default-toplevel.flow')
+ if config.trace_memory:
+ categories.append('disabled-by-default-memory')
+ if config.trace_scheduler:
+ categories.append('disabled-by-default-blink.scheduler')
+ categories.append('disabled-by-default-cc.debug.scheduler')
+ categories.append('disabled-by-default-renderer.scheduler')
+ if config.chrome_categories:
+ categories += config.chrome_categories.split(',')
+ return categories
diff --git a/catapult/systrace/profile_chrome/chrome_tracing_agent_unittest.py b/catapult/systrace/profile_chrome/chrome_tracing_agent_unittest.py
index edae8afb..dc387595 100644
--- a/catapult/systrace/profile_chrome/chrome_tracing_agent_unittest.py
+++ b/catapult/systrace/profile_chrome/chrome_tracing_agent_unittest.py
@@ -6,10 +6,20 @@ import json
from profile_chrome import chrome_tracing_agent
from profile_chrome import agents_unittest
+from systrace import decorators
class ChromeAgentTest(agents_unittest.BaseAgentTest):
+ # TODO(washingtonp): This test seems to fail on the version of Android
+ # currently on the Trybot servers (KTU84P), although it works on Android M.
+ # Either upgrade the version of Android on the Trybot servers or determine
+ # if there is a way to run this agent on Android KTU84P.
+ @decorators.Disabled
def testGetCategories(self):
+ curr_browser = self.GetChromeProcessID()
+ if curr_browser == None:
+ self.StartBrowser()
+
categories = \
chrome_tracing_agent.ChromeTracingAgent.GetCategories(
self.device, self.package_info)
@@ -18,15 +28,24 @@ class ChromeAgentTest(agents_unittest.BaseAgentTest):
self.assertTrue(categories[0])
self.assertTrue(categories[1])
+ # TODO(washingtonp): This test is pretty flaky on the version of Android
+ # currently on the Trybot servers (KTU84P), although it works on Android M.
+ # Either upgrade the version of Android on the Trybot servers or determine
+ # if there is a way to run this agent on Android KTU84P.
+ @decorators.Disabled
def testTracing(self):
+ curr_browser = self.GetChromeProcessID()
+ if curr_browser == None:
+ self.StartBrowser()
+
categories = '*'
ring_buffer = False
agent = chrome_tracing_agent.ChromeTracingAgent(self.device,
self.package_info,
- categories,
ring_buffer)
-
- agent.StartAgentTracing(None, None)
+ agent.StartAgentTracing(chrome_tracing_agent.ChromeConfig(categories, None,
+ None, None, None, None, None, None, ring_buffer, self.device,
+ self.package_info))
agent.StopAgentTracing()
result = agent.GetResults()
json.loads(result.raw_data)
diff --git a/catapult/systrace/profile_chrome/ddms_tracing_agent.py b/catapult/systrace/profile_chrome/ddms_tracing_agent.py
index 3c6a2320..276a3b9f 100644
--- a/catapult/systrace/profile_chrome/ddms_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/ddms_tracing_agent.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import optparse
import os
import py_utils
import re
@@ -32,7 +33,7 @@ class DdmsAgent(tracing_agents.TracingAgent):
return False
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
- def StartAgentTracing(self, options, categories, timeout=None):
+ def StartAgentTracing(self, config, timeout=None):
self._output_file = (
'/data/local/tmp/ddms-profile-%s' % util.GetTraceTimestamp())
cmd = 'am profile start '
@@ -40,10 +41,12 @@ class DdmsAgent(tracing_agents.TracingAgent):
cmd += '--sampling %d ' % _DDMS_SAMPLING_FREQUENCY_US
cmd += '%s %s' % (self._package, self._output_file)
self._device.RunShellCommand(cmd)
+ return True
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
def StopAgentTracing(self, timeout=None):
self._device.RunShellCommand('am profile stop %s' % self._package)
+ return True
@py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
def GetResults(self, timeout=None):
@@ -64,5 +67,29 @@ class DdmsAgent(tracing_agents.TracingAgent):
return False
def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ # pylint: disable=unused-argument
assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
'recorded since explicit clock sync is not supported.')
+
+
+class DdmsConfig(tracing_agents.TracingConfig):
+ def __init__(self, device, package_info, ddms):
+ tracing_agents.TracingConfig.__init__(self)
+ self.device = device
+ self.package_info = package_info
+ self.ddms = ddms
+
+
+def try_create_agent(config):
+ if config.ddms:
+ return DdmsAgent(config.device, config.package_info)
+ return None
+
+def add_options(parser):
+ options = optparse.OptionGroup(parser, 'Java tracing')
+ options.add_option('--ddms', help='Trace Java execution using DDMS '
+ 'sampling.', action='store_true')
+ return options
+
+def get_config(options):
+ return DdmsConfig(options.device, options.package_info, options.ddms)
diff --git a/catapult/systrace/profile_chrome/ddms_tracing_agent_unittest.py b/catapult/systrace/profile_chrome/ddms_tracing_agent_unittest.py
index a8ccd504..c3878d0e 100644
--- a/catapult/systrace/profile_chrome/ddms_tracing_agent_unittest.py
+++ b/catapult/systrace/profile_chrome/ddms_tracing_agent_unittest.py
@@ -4,14 +4,19 @@
from profile_chrome import agents_unittest
from profile_chrome import ddms_tracing_agent
+from systrace import decorators
class DdmsAgentTest(agents_unittest.BaseAgentTest):
+ # TODO(washingtonp): The DDMS test is flaky on the Tryserver, but it
+ # consistently passes on Android M. Need to figure out why the result data
+ # does not start with '*version' and why the test is flaky.
+ @decorators.Disabled
def testTracing(self):
agent = ddms_tracing_agent.DdmsAgent(self.device, self.package_info)
try:
- agent.StartAgentTracing(None, None)
+ agent.StartAgentTracing(None)
finally:
agent.StopAgentTracing()
diff --git a/catapult/systrace/profile_chrome/fake_agent_1.py b/catapult/systrace/profile_chrome/fake_agent_1.py
new file mode 100644
index 00000000..62889f45
--- /dev/null
+++ b/catapult/systrace/profile_chrome/fake_agent_1.py
@@ -0,0 +1,69 @@
+# 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 optparse
+import tempfile
+
+from systrace import trace_result
+from systrace import tracing_agents
+
+
+class FakeAgent(object):
+ def __init__(self, contents='fake-contents'):
+ self.contents = contents
+ self.stopped = False
+ self.filename = None
+ self.config = None
+ self.timeout = None
+
+ def StartAgentTracing(self, config, timeout=None):
+ self.config = config
+ self.timeout = timeout
+ return True
+
+ # pylint: disable=unused-argument
+ def StopAgentTracing(self, timeout=None):
+ self.stopped = True
+ return True
+
+ # pylint: disable=unused-argument
+ def GetResults(self, timeout=None):
+ trace_data = open(self._PullTrace()).read()
+ return trace_result.TraceResult('fakeData', trace_data)
+
+ def _PullTrace(self):
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ self.filename = f.name
+ f.write(self.contents)
+ return f.name
+
+ # pylint: disable=no-self-use
+ def SupportsExplicitClockSync(self):
+ return False
+
+ # pylint: disable=unused-argument, no-self-use
+ def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ print ('Clock sync marker cannot be recorded since explicit clock sync '
+ 'is not supported.')
+
+ def __repr__(self):
+ return 'faketrace'
+
+
+class FakeConfig(tracing_agents.TracingConfig):
+ def __init__(self):
+ tracing_agents.TracingConfig.__init__(self)
+
+
+# pylint: disable=unused-argument
+def try_create_agent(config):
+ return FakeAgent()
+
+def add_options(parser):
+ options = optparse.OptionGroup(parser, 'Fake options.')
+ return options
+
+# pylint: disable=unused-argument
+def get_config(options):
+ return FakeConfig()
diff --git a/catapult/systrace/profile_chrome/fake_agent_2.py b/catapult/systrace/profile_chrome/fake_agent_2.py
new file mode 100644
index 00000000..477b6c75
--- /dev/null
+++ b/catapult/systrace/profile_chrome/fake_agent_2.py
@@ -0,0 +1,68 @@
+# 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 optparse
+import tempfile
+
+from systrace import trace_result
+from systrace import tracing_agents
+
+
+class FakeAgent2(object):
+ def __init__(self, contents='fake-contents'):
+ self.contents = contents
+ self.stopped = False
+ self.config = None
+ self.filename = None
+
+ # pylint: disable=unused-argument
+ def StartAgentTracing(self, config, timeout=None):
+ self.config = config
+ return True
+
+ # pylint: disable=unused-argument
+ def StopAgentTracing(self, timeout=None):
+ self.stopped = True
+ return True
+
+ # pylint: disable=unused-argument
+ def GetResults(self, timeout=None):
+ trace_data = open(self._PullTrace()).read()
+ return trace_result.TraceResult('fakeDataTwo', trace_data)
+
+ def _PullTrace(self):
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ self.filename = f.name
+ f.write(self.contents)
+ return f.name
+
+ # pylint: disable=no-self-use
+ def SupportsExplicitClockSync(self):
+ return False
+
+ # pylint: disable=unused-argument, no-self-use
+ def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ print ('Clock sync marker cannot be recorded since explicit clock sync '
+ 'is not supported.')
+
+ def __repr__(self):
+ return 'faketracetwo'
+
+
+class FakeConfig(tracing_agents.TracingConfig):
+ def __init__(self):
+ tracing_agents.TracingConfig.__init__(self)
+
+
+# pylint: disable=unused-argument
+def try_create_agent(config):
+ return FakeAgent2()
+
+def add_options(parser):
+ options = optparse.OptionGroup(parser, 'Fake options.')
+ return options
+
+# pylint: disable=unused-argument
+def get_config(options):
+ return FakeConfig()
diff --git a/catapult/systrace/profile_chrome/flags.py b/catapult/systrace/profile_chrome/flags.py
index 17373535..c9511236 100644
--- a/catapult/systrace/profile_chrome/flags.py
+++ b/catapult/systrace/profile_chrome/flags.py
@@ -4,25 +4,13 @@
import optparse
-def AtraceOptions(parser):
- atrace_opts = optparse.OptionGroup(parser, 'Systrace tracing options')
- atrace_opts.add_option('-s', '--systrace', help='Capture a systrace with '
- 'the chosen comma-delimited systrace categories. You'
- ' can also capture a combined Chrome + systrace by '
- 'enabling both types of categories. Use "list" to '
- 'see the available categories. Systrace is disabled'
- ' by default. Note that in this case, Systrace is '
- 'synonymous with Atrace.',
- metavar='ATRACE_CATEGORIES',
- dest='atrace_categories', default='')
- return atrace_opts
-
def OutputOptions(parser):
output_options = optparse.OptionGroup(parser, 'Output options')
- output_options.add_option('-o', '--output', help='Save trace output to file.')
+ output_options.add_option('-o', '--output', dest='output_file',
+ help='Save trace output to file.')
output_options.add_option('--json', help='Save trace as raw JSON instead of '
- 'HTML.', action='store_true')
+ 'HTML.', dest='write_json')
output_options.add_option('--view', help='Open resulting trace file in a '
'browser.', action='store_true')
return output_options
diff --git a/catapult/systrace/profile_chrome/main.py b/catapult/systrace/profile_chrome/main.py
index c1cf2291..b448f92b 100755
--- a/catapult/systrace/profile_chrome/main.py
+++ b/catapult/systrace/profile_chrome/main.py
@@ -21,51 +21,8 @@ from profile_chrome import ui
from devil.android import device_utils
-_DEFAULT_CHROME_CATEGORIES = '_DEFAULT_CHROME_CATEGORIES'
-
-
-def _ComputeChromeCategories(options):
- categories = []
- if options.trace_frame_viewer:
- categories.append('disabled-by-default-cc.debug')
- if options.trace_ubercompositor:
- categories.append('disabled-by-default-cc.debug*')
- if options.trace_gpu:
- categories.append('disabled-by-default-gpu.debug*')
- if options.trace_flow:
- categories.append('disabled-by-default-toplevel.flow')
- if options.trace_memory:
- categories.append('disabled-by-default-memory')
- if options.trace_scheduler:
- categories.append('disabled-by-default-blink.scheduler')
- categories.append('disabled-by-default-cc.debug.scheduler')
- categories.append('disabled-by-default-renderer.scheduler')
- if options.chrome_categories:
- categories += options.chrome_categories.split(',')
- return categories
-
-
-def _ComputeAtraceCategories(options):
- if not options.atrace_categories:
- return []
- return options.atrace_categories.split(',')
-
-
-def _ComputePerfCategories(options):
- if not perf_tracing_agent.PerfProfilerAgent.IsSupported():
- return []
- if not options.perf_categories:
- return []
- return options.perf_categories.split(',')
-
-
-def _OptionalValueCallback(default_value):
- def callback(option, _, __, parser): # pylint: disable=unused-argument
- value = default_value
- if parser.rargs and not parser.rargs[0].startswith('-'):
- value = parser.rargs.pop(0)
- setattr(parser.values, option.dest, value)
- return callback
+_PROFILE_CHROME_AGENT_MODULES = [chrome_tracing_agent, ddms_tracing_agent,
+ perf_tracing_agent, atrace_tracing_agent]
def _CreateOptionParser():
@@ -78,7 +35,7 @@ def _CreateOptionParser():
timed_options = optparse.OptionGroup(parser, 'Timed tracing')
timed_options.add_option('-t', '--time', help='Profile for N seconds and '
'download the resulting trace.', metavar='N',
- type='float')
+ type='float', dest='trace_time')
parser.add_option_group(timed_options)
cont_options = optparse.OptionGroup(parser, 'Continuous tracing')
@@ -90,53 +47,6 @@ def _CreateOptionParser():
action='store_true')
parser.add_option_group(cont_options)
- chrome_opts = optparse.OptionGroup(parser, 'Chrome tracing options')
- chrome_opts.add_option('-c', '--categories', help='Select Chrome tracing '
- 'categories with comma-delimited wildcards, '
- 'e.g., "*", "cat1*,-cat1a". Omit this option to trace '
- 'Chrome\'s default categories. Chrome tracing can be '
- 'disabled with "--categories=\'\'". Use "list" to '
- 'see the available categories.',
- metavar='CHROME_CATEGORIES', dest='chrome_categories',
- default=_DEFAULT_CHROME_CATEGORIES)
- chrome_opts.add_option('--trace-cc',
- help='Deprecated, use --trace-frame-viewer.',
- action='store_true')
- chrome_opts.add_option('--trace-frame-viewer',
- help='Enable enough trace categories for '
- 'compositor frame viewing.', action='store_true')
- chrome_opts.add_option('--trace-ubercompositor',
- help='Enable enough trace categories for '
- 'ubercompositor frame data.', action='store_true')
- chrome_opts.add_option('--trace-gpu', help='Enable extra trace categories '
- 'for GPU data.', action='store_true')
- chrome_opts.add_option('--trace-flow', help='Enable extra trace categories '
- 'for IPC message flows.', action='store_true')
- chrome_opts.add_option('--trace-memory', help='Enable extra trace categories '
- 'for memory profile. (tcmalloc required)',
- action='store_true')
- chrome_opts.add_option('--trace-scheduler', help='Enable extra trace '
- 'categories for scheduler state',
- action='store_true')
- parser.add_option_group(chrome_opts)
-
- parser.add_option_group(flags.AtraceOptions(parser))
-
- if perf_tracing_agent.PerfProfilerAgent.IsSupported():
- perf_opts = optparse.OptionGroup(parser, 'Perf profiling options')
- perf_opts.add_option('-p', '--perf', help='Capture a perf profile with '
- 'the chosen comma-delimited event categories. '
- 'Samples CPU cycles by default. Use "list" to see '
- 'the available sample types.', action='callback',
- default='', callback=_OptionalValueCallback('cycles'),
- metavar='PERF_CATEGORIES', dest='perf_categories')
- parser.add_option_group(perf_opts)
-
- ddms_options = optparse.OptionGroup(parser, 'Java tracing')
- ddms_options.add_option('--ddms', help='Trace Java execution using DDMS '
- 'sampling.', action='store_true')
- parser.add_option_group(ddms_options)
-
parser.add_option_group(flags.OutputOptions(parser))
browsers = sorted(profiler.GetSupportedBrowsers().keys())
@@ -151,7 +61,12 @@ def _CreateOptionParser():
parser.add_option('-d', '--device', help='The Android device ID to use, '
'defaults to the value of ANDROID_SERIAL environment '
'variable. If not specified, only 0 or 1 connected '
- 'devices are supported.')
+ 'devices are supported.', dest='device_serial_number')
+
+ # Add options from profile_chrome agents.
+ for module in _PROFILE_CHROME_AGENT_MODULES:
+ parser.add_option_group(module.add_options(parser))
+
return parser
@@ -170,9 +85,25 @@ When in doubt, just try out --trace-frame-viewer.
if options.verbose:
logging.getLogger().setLevel(logging.DEBUG)
- device = device_utils.DeviceUtils.HealthyDevices(device_arg=options.device)[0]
+ device = device_utils.DeviceUtils.HealthyDevices(device_arg=
+ options.device_serial_number)[0]
package_info = profiler.GetSupportedBrowsers()[options.browser]
+ options.device = device
+ options.package_info = package_info
+
+ # Add options that are present in Systrace but not in profile_chrome (since
+ # they both use the same tracing controller).
+ # TODO(washingtonp): Once Systrace uses all of the profile_chrome agents,
+ # manually setting these options will no longer be necessary and should be
+ # removed.
+ options.list_categories = None
+ options.link_assets = None
+ options.asset_dir = None
+ options.timeout = None
+ options.collection_timeout = None
+ options.target = None
+
if options.chrome_categories in ['list', 'help']:
ui.PrintMessage('Collecting record categories list...', eol='')
record_categories = []
@@ -203,54 +134,23 @@ When in doubt, just try out --trace-frame-viewer.
perf_tracing_agent.PerfProfilerAgent.GetCategories(device)))
return 0
- if not options.time and not options.continuous:
+ if not options.trace_time and not options.continuous:
ui.PrintMessage('Time interval or continuous tracing should be specified.')
return 1
- chrome_categories = _ComputeChromeCategories(options)
- atrace_categories = _ComputeAtraceCategories(options)
- perf_categories = _ComputePerfCategories(options)
-
- if chrome_categories and 'webview' in atrace_categories:
+ if options.chrome_categories and 'webview' in options.atrace_categories:
logging.warning('Using the "webview" category in atrace together with '
'Chrome tracing results in duplicate trace events.')
- enabled_agents = []
- if chrome_categories:
- enabled_agents.append(
- chrome_tracing_agent.ChromeTracingAgent(device,
- package_info,
- chrome_categories,
- options.ring_buffer,
- options.trace_memory))
- if atrace_categories:
- enabled_agents.append(
- atrace_tracing_agent.AtraceAgent(device,
- atrace_categories,
- options.ring_buffer))
-
- if perf_categories:
- enabled_agents.append(
- perf_tracing_agent.PerfProfilerAgent(device,
- perf_categories))
-
- if options.ddms:
- enabled_agents.append(
- ddms_tracing_agent.DdmsAgent(device,
- package_info))
-
- if not enabled_agents:
- ui.PrintMessage('No trace categories enabled.')
- return 1
-
- if options.output:
- options.output = os.path.expanduser(options.output)
+ if options.output_file:
+ options.output_file = os.path.expanduser(options.output_file)
result = profiler.CaptureProfile(
- enabled_agents,
- options.time if not options.continuous else 0,
- output=options.output,
+ options,
+ options.trace_time if not options.continuous else 0,
+ _PROFILE_CHROME_AGENT_MODULES,
+ output=options.output_file,
compress=options.compress,
- write_json=options.json)
+ write_json=options.write_json)
if options.view:
if sys.platform == 'darwin':
os.system('/usr/bin/open %s' % os.path.abspath(result))
diff --git a/catapult/systrace/profile_chrome/perf_tracing_agent.py b/catapult/systrace/profile_chrome/perf_tracing_agent.py
index 15dd5c0c..dc03bb80 100644
--- a/catapult/systrace/profile_chrome/perf_tracing_agent.py
+++ b/catapult/systrace/profile_chrome/perf_tracing_agent.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import logging
+import optparse
import os
import py_utils
import signal
@@ -93,12 +94,12 @@ class _PerfProfiler(object):
class PerfProfilerAgent(tracing_agents.TracingAgent):
- def __init__(self, device, categories):
+ def __init__(self, device):
tracing_agents.TracingAgent.__init__(self)
self._device = device
- self._categories = categories
self._perf_binary = self._PrepareDevice(device)
self._perf_instance = None
+ self._categories = None
def __repr__(self):
return 'perf profile'
@@ -121,16 +122,19 @@ class PerfProfilerAgent(tracing_agents.TracingAgent):
return device.RunShellCommand('%s list' % perf_binary)
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
- def StartAgentTracing(self, options, categories, timeout=None):
+ def StartAgentTracing(self, config, timeout=None):
+ self._categories = _ComputePerfCategories(config)
self._perf_instance = _PerfProfiler(self._device,
self._perf_binary,
self._categories)
+ return True
@py_utils.Timeout(tracing_agents.START_STOP_TIMEOUT)
def StopAgentTracing(self, timeout=None):
if not self._perf_instance:
return
self._perf_instance.SignalAndWait()
+ return True
@py_utils.Timeout(tracing_agents.GET_RESULTS_TIMEOUT)
def GetResults(self, timeout=None):
@@ -202,5 +206,48 @@ class PerfProfilerAgent(tracing_agents.TracingAgent):
return False
def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
+ # pylint: disable=unused-argument
assert self.SupportsExplicitClockSync(), ('Clock sync marker cannot be '
'recorded since explicit clock sync is not supported.')
+
+def _OptionalValueCallback(default_value):
+ def callback(option, _, __, parser): # pylint: disable=unused-argument
+ value = default_value
+ if parser.rargs and not parser.rargs[0].startswith('-'):
+ value = parser.rargs.pop(0)
+ setattr(parser.values, option.dest, value)
+ return callback
+
+
+class PerfConfig(tracing_agents.TracingConfig):
+ def __init__(self, perf_categories, device):
+ tracing_agents.TracingConfig.__init__(self)
+ self.perf_categories = perf_categories
+ self.device = device
+
+
+def try_create_agent(config):
+ if config.perf_categories:
+ return PerfProfilerAgent(config.device)
+ return None
+
+def add_options(parser):
+ options = optparse.OptionGroup(parser, 'Perf profiling options')
+ options.add_option('-p', '--perf', help='Capture a perf profile with '
+ 'the chosen comma-delimited event categories. '
+ 'Samples CPU cycles by default. Use "list" to see '
+ 'the available sample types.', action='callback',
+ default='', callback=_OptionalValueCallback('cycles'),
+ metavar='PERF_CATEGORIES', dest='perf_categories')
+ parser.add_option_group(options)
+ return options
+
+def get_config(options):
+ return PerfConfig(options.perf_categories, options.device)
+
+def _ComputePerfCategories(config):
+ if not PerfProfilerAgent.IsSupported():
+ return []
+ if not config.perf_categories:
+ return []
+ return config.perf_categories.split(',')
diff --git a/catapult/systrace/profile_chrome/perf_tracing_agent_unittest.py b/catapult/systrace/profile_chrome/perf_tracing_agent_unittest.py
index 1367e9b7..8f8a7f7a 100644
--- a/catapult/systrace/profile_chrome/perf_tracing_agent_unittest.py
+++ b/catapult/systrace/profile_chrome/perf_tracing_agent_unittest.py
@@ -7,9 +7,11 @@ import json
from profile_chrome import agents_unittest
from profile_chrome import perf_tracing_agent
from profile_chrome import ui
+from systrace import decorators
class PerfProfilerAgentTest(agents_unittest.BaseAgentTest):
+ @decorators.ClientOnlyTest
def testGetCategories(self):
if not perf_tracing_agent.PerfProfilerAgent.IsSupported():
return
@@ -17,16 +19,19 @@ class PerfProfilerAgentTest(agents_unittest.BaseAgentTest):
perf_tracing_agent.PerfProfilerAgent.GetCategories(self.device)
assert 'cycles' in ' '.join(categories)
+ # TODO(washingtonp): Try enabling this test for the SimpleperfProfilerAgent,
+ # which will be added later.
+ @decorators.Disabled
def testTracing(self):
if not perf_tracing_agent.PerfProfilerAgent.IsSupported():
return
ui.EnableTestMode()
- categories = ['cycles']
- agent = perf_tracing_agent.PerfProfilerAgent(self.device,
- categories)
+ categories = 'cycles'
+ agent = perf_tracing_agent.PerfProfilerAgent(self.device)
try:
- agent.StartAgentTracing(None, None)
+ agent.StartAgentTracing(perf_tracing_agent.PerfConfig(categories,
+ self.device))
finally:
agent.StopAgentTracing()
diff --git a/catapult/systrace/profile_chrome/profiler.py b/catapult/systrace/profile_chrome/profiler.py
index 6f0c3e25..a52faf1e 100644
--- a/catapult/systrace/profile_chrome/profiler.py
+++ b/catapult/systrace/profile_chrome/profiler.py
@@ -5,33 +5,29 @@
import time
from devil.android.constants import chrome
+from profile_chrome import chrome_startup_tracing_agent
from profile_chrome import chrome_tracing_agent
from profile_chrome import ui
from profile_chrome import util
from systrace import output_generator
+from systrace import tracing_controller
-def _StartTracing(agents):
- for agent in agents:
- agent.StartAgentTracing(None, None)
-
-
-def _StopTracing(agents):
- for agent in agents:
- agent.StopAgentTracing()
-
-
-def _GetResults(agents, output, compress, write_json, interval):
+def _GetResults(trace_results, controller, output, compress, write_json,
+ interval):
ui.PrintMessage('Downloading...', eol='')
# Wait for the trace file to get written.
time.sleep(1)
- trace_results = []
- for agent in agents:
+ for agent in controller.get_child_agents:
if isinstance(agent, chrome_tracing_agent.ChromeTracingAgent):
time.sleep(interval / 4)
- trace_results.append(agent.GetResults())
+
+ # Ignore the systraceController because it will not contain any results,
+ # instead being in charge of collecting results.
+ trace_results = [x for x in controller.all_results if not (x.source_name ==
+ 'systraceController')]
if not trace_results:
ui.PrintMessage('No results')
@@ -76,14 +72,15 @@ def GetSupportedBrowsers():
return supported_browsers
-def CaptureProfile(agents, interval, output=None, compress=False,
- write_json=False):
+def CaptureProfile(options, interval, modules, output=None,
+ compress=False, write_json=False):
"""Records a profiling trace saves the result to a file.
Args:
- agents: List of tracing agents.
+ options: Command line options.
interval: Time interval to capture in seconds. An interval of None (or 0)
continues tracing until stopped by the user.
+ modules: The list of modules to initialize the tracing controller with.
output: Output file name or None to use an automatically generated name.
compress: If True, the result will be compressed either with gzip or zip
depending on the number of captured subtraces.
@@ -92,20 +89,32 @@ def CaptureProfile(agents, interval, output=None, compress=False,
Returns:
Path to saved profile.
"""
- trace_type = ' + '.join(map(str, agents))
+ agents_with_config = tracing_controller.CreateAgentsWithConfig(options,
+ modules)
+ if chrome_startup_tracing_agent in modules:
+ controller_config = tracing_controller.GetChromeStartupControllerConfig(
+ options)
+ else:
+ controller_config = tracing_controller.GetControllerConfig(options)
+ controller = tracing_controller.TracingController(agents_with_config,
+ controller_config)
try:
- _StartTracing(agents)
+ result = controller.StartTracing()
+ trace_type = controller.GetTraceType()
+ if not result:
+ print 'Trace starting failed.'
if interval:
ui.PrintMessage(('Capturing %d-second %s. Press Enter to stop early...' %
- (interval, trace_type)), eol='')
+ (interval, trace_type)), eol='')
ui.WaitForEnter(interval)
else:
ui.PrintMessage('Capturing %s. Press Enter to stop...' % trace_type,
- eol='')
+ eol='')
raw_input()
+ all_results = controller.StopTracing()
finally:
- _StopTracing(agents)
- if interval:
- ui.PrintMessage('done')
+ if interval:
+ ui.PrintMessage('done')
- return _GetResults(agents, output, compress, write_json, interval)
+ return _GetResults(all_results, controller, output, compress, write_json,
+ interval)
diff --git a/catapult/systrace/profile_chrome/profiler_unittest.py b/catapult/systrace/profile_chrome/profiler_unittest.py
index 99ca6111..cd7af956 100644
--- a/catapult/systrace/profile_chrome/profiler_unittest.py
+++ b/catapult/systrace/profile_chrome/profiler_unittest.py
@@ -3,88 +3,52 @@
# found in the LICENSE file.
import os
-import tempfile
import unittest
import zipfile
from profile_chrome import profiler
from profile_chrome import ui
-from systrace import trace_result
-
-
-class FakeAgent(object):
- def __init__(self, contents='fake-contents'):
- self.contents = contents
- self.stopped = False
- self.filename = None
- self.options = None
- self.categories = None
- self.timeout = None
-
- def StartAgentTracing(self, options, categories, timeout=None):
- self.options = options
- self.categories = categories
- self.timeout = timeout
-
- # pylint: disable=unused-argument
- def StopAgentTracing(self, timeout=None):
- self.stopped = True
-
- # pylint: disable=unused-argument
- def GetResults(self, timeout=None):
- trace_data = open(self.PullTrace()).read()
- return trace_result.TraceResult('fakeData', trace_data)
-
- def PullTrace(self):
- with tempfile.NamedTemporaryFile(delete=False) as f:
- self.filename = f.name
- f.write(self.contents)
- return f.name
-
- # pylint: disable=no-self-use
- def SupportsExplicitClockSync(self):
- return False
-
- # pylint: disable=unused-argument, no-self-use
- def RecordClockSyncMarker(self, sync_id, did_record_sync_marker_callback):
- print ('Clock sync marker cannot be recorded since explicit clock sync '
- 'is not supported.')
-
- def __repr__(self):
- return 'faketrace'
+from profile_chrome import fake_agent_1
+from profile_chrome import fake_agent_2
+from systrace import decorators
+from systrace import tracing_controller
class ProfilerTest(unittest.TestCase):
def setUp(self):
ui.EnableTestMode()
+ self._tracing_options = tracing_controller.TracingControllerConfig(None,
+ None, None, None, None, None, None, None, None, None)
+ @decorators.ClientOnlyTest
def testCaptureBasicProfile(self):
- agent = FakeAgent()
- result = profiler.CaptureProfile([agent], 1)
+ result = profiler.CaptureProfile(self._tracing_options, 1, [fake_agent_1])
try:
- self.assertTrue(agent.stopped)
self.assertTrue(os.path.exists(result))
self.assertTrue(result.endswith('.html'))
finally:
if os.path.exists(result):
os.remove(result)
+ @decorators.ClientOnlyTest
def testCaptureJsonProfile(self):
- agent = FakeAgent()
- result = profiler.CaptureProfile([agent], 1, write_json=True)
+ result = profiler.CaptureProfile(self._tracing_options, 1,
+ [fake_agent_2], write_json=True)
try:
self.assertFalse(result.endswith('.html'))
with open(result) as f:
- self.assertEquals(f.read(), agent.contents)
+ self.assertEquals(f.read(), 'fake-contents')
finally:
if os.path.exists(result):
os.remove(result)
+ @decorators.ClientOnlyTest
def testCaptureMultipleProfiles(self):
- agents = [FakeAgent('c1'), FakeAgent('c2')]
- result = profiler.CaptureProfile(agents, 1, write_json=True)
+ result = profiler.CaptureProfile(self._tracing_options, 1,
+ [fake_agent_1, fake_agent_2],
+ write_json=True)
try:
self.assertTrue(result.endswith('.zip'))