diff options
Diffstat (limited to 'chromium/tools/telemetry/telemetry')
22 files changed, 55 insertions, 755 deletions
diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py deleted file mode 100644 index 9228df89b0e..00000000000 --- a/chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright 2013 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. diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py deleted file mode 100644 index 2eb01f2eb27..00000000000 --- a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2013 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 telemetry.core.backends import browser_backend -from telemetry.core.backends.webdriver import webdriver_tab_list_backend - -class WebDriverBrowserBackend(browser_backend.BrowserBackend): - """The webdriver-based backend for controlling a locally-executed browser - instance, on Linux, Mac, and Windows. - """ - - def __init__(self, driver_creator, supports_extensions, options): - super(WebDriverBrowserBackend, self).__init__( - is_content_shell=False, - supports_extensions=supports_extensions, - options=options, - tab_list_backend=webdriver_tab_list_backend.WebDriverTabListBackend) - - self._driver_creator = driver_creator - self._driver = None - self.webpagereplay_local_http_port = 80 - self.webpagereplay_local_https_port = 443 - self.webpagereplay_remote_http_port = self.webpagereplay_local_http_port - self.webpagereplay_remote_https_port = self.webpagereplay_local_https_port - - def Start(self): - assert not self._driver - self._driver = self._driver_creator() - - @property - def driver(self): - assert self._driver - return self._driver - - @property - def supports_tab_control(self): - # Based on webdriver protocol API, only closing a tab is supported while - # activating or creating a tab is not. Thus, tab control is not supported. - return False - - @property - def supports_tracing(self): - # Tracing is not available in IE/Firefox yet and not supported through - # webdriver API. - return False - - def GetProcessName(self, _): - # Leave implementation details to subclass as process name depends on the - # type of browser. - raise NotImplementedError() - - def Close(self): - if self._driver: - self._driver.quit() - self._driver = None - - def CreateForwarder(self, *port_pairs): - return browser_backend.DoNothingForwarder(*port_pairs) - - def IsBrowserRunning(self): - # Assume the browser is running if not explicitly closed. - return self._driver is not None - - def GetStandardOutput(self): - # TODO(chrisgao): check if python client can get stdout of browsers. - return '' - - def __del__(self): - self.Close() diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py deleted file mode 100644 index 13c298946ec..00000000000 --- a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2013 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. -"""Finds desktop browsers that can be controlled by telemetry.""" - -import logging -import os -import sys - -from telemetry.core import browser -from telemetry.core import possible_browser -from telemetry.core import platform -from telemetry.core import util -from telemetry.core.backends.webdriver import webdriver_browser_backend - -# Try to import the selenium python lib which may be not available. -try: - from selenium import webdriver # pylint: disable=F0401 -except ImportError: - webdriver = None - pylib = os.path.join(util.GetChromiumSrcDir(), - 'third_party', 'webdriver', 'pylib') - if (os.path.isdir(pylib)): - sys.path.insert(0, pylib) - try: - from selenium import webdriver # pylint: disable=F0401 - except ImportError: - webdriver = None - -ALL_BROWSER_TYPES = '' -if webdriver: - ALL_BROWSER_TYPES = ','.join([ - 'internet-explorer', - 'internet-explorer-x64']) -else: - logging.warning('Webdriver backend is unsupported without selenium pylib. ' - 'For installation of selenium pylib, please refer to ' - 'https://code.google.com/p/selenium/wiki/PythonBindings.') - - -class PossibleWebDriverBrowser(possible_browser.PossibleBrowser): - """A browser that can be controlled through webdriver API.""" - - def __init__(self, browser_type, options): - super(PossibleWebDriverBrowser, self).__init__(browser_type, options) - - def CreateWebDriverBackend(self): - raise NotImplementedError() - - def Create(self): - backend = self.CreateWebDriverBackend() - b = browser.Browser(backend, platform.CreatePlatformBackendForCurrentOS()) - return b - - def SupportsOptions(self, options): - # TODO(chrisgao): Check if some options are not supported. - return True - - @property - def last_modification_time(self): - return -1 - - def SelectDefaultBrowser(self, possible_browsers): # pylint: disable=W0613 - return None - - -class PossibleDesktopIE(PossibleWebDriverBrowser): - def __init__(self, browser_type, options, architecture): - super(PossibleDesktopIE, self).__init__(browser_type, options) - self._architecture = architecture - - def CreateWebDriverBackend(self): - assert webdriver - def DriverCreator(): - # TODO(chrisgao): Check in IEDriverServer.exe and specify path to it when - # creating the webdriver instance. crbug.com/266170 - return webdriver.Ie() - return webdriver_browser_backend.WebDriverBrowserBackend( - DriverCreator, False, self.options) - - -def FindAllAvailableBrowsers(options): - """Finds all the desktop browsers available on this machine.""" - browsers = [] - if not webdriver: - return browsers - - # Look for the IE browser in the standard location. - if sys.platform.startswith('win'): - ie_path = os.path.join('Internet Explorer', 'iexplore.exe') - win_search_paths = { - '32' : { 'path' : os.getenv('PROGRAMFILES(X86)'), - 'type' : 'internet-explorer'}, - '64' : { 'path' : os.getenv('PROGRAMFILES'), - 'type' : 'internet-explorer-x64'}} - for architecture, ie_info in win_search_paths.iteritems(): - if not ie_info['path']: - continue - if os.path.exists(os.path.join(ie_info['path'], ie_path)): - browsers.append( - PossibleDesktopIE(ie_info['type'], options, architecture)) - - return browsers diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py deleted file mode 100644 index df2e7ae62e3..00000000000 --- a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2013 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 logging - -# TODO(chrisgao): Make png_bitmap sharable for both chrome and webdriver. -from telemetry.core.chrome import png_bitmap - -class WebDriverTabBackend(object): - def __init__(self, browser_backend, window_handle): - self._browser_backend = browser_backend - self._window_handle = window_handle - - def Disconnect(self): - pass - - @property - def browser(self): - return self._browser_backend.browser - - @property - def window_handle(self): - return self._window_handle - - @property - def url(self): - self._browser_backend.driver.switch_to_window(self._window_handle) - return self._browser_backend.driver.current_url - - def Activate(self): - # Webdriver doesn't support tab control. - raise NotImplementedError() - - def Close(self): - self._browser_backend.driver.switch_to_window(self._window_handle) - self._browser_backend.driver.close() - - def WaitForDocumentReadyStateToBeComplete(self, timeout=None): - # TODO(chrisgao): Double check of document state. - pass - - def WaitForDocumentReadyStateToBeInteractiveOrBetter(self, timeout=None): - # TODO(chrisgao): Double check of document state. - pass - - @property - def screenshot_supported(self): - return True - - def Screenshot(self, timeout=None): # pylint: disable=W0613 - if timeout: - logging.warning('timeout is not supported') - self._browser_backend.driver.switch_to_window(self._window_handle) - snap = self._browser_backend.driver.get_screenshot_as_base64() - if snap: - return png_bitmap.PngBitmap(snap) - return None - - @property - def message_output_stream(self): - # Webdriver has no API for grabbing console messages. - raise NotImplementedError() - - @message_output_stream.setter - def message_output_stream(self, stream): - raise NotImplementedError() - - def GetDOMStats(self, timeout=None): - # Webdriver has no API for DOM status. - raise NotImplementedError() - - def PerformActionAndWaitForNavigate(self, action_function, _): - # TODO(chrisgao): Double check of navigation. - action_function() - - def Navigate(self, url, script_to_evaluate_on_commit=None, timeout=None): - if script_to_evaluate_on_commit: - raise NotImplementedError('script_to_evaluate_on_commit is NOT supported') - self._browser_backend.driver.switch_to_window(self._window_handle) - if timeout: - self._browser_backend.driver.set_page_load_timeout(timeout * 1000) - self._browser_backend.driver.get(url) - - def GetCookieByName(self, name, timeout=None): - if timeout: - logging.warning('timeout is not supported') - self._browser_backend.driver.switch_to_window(self._window_handle) - cookie = self._browser_backend.driver.get_cookie(name) - if cookie: - return cookie['value'] - return None - - def ExecuteJavaScript(self, expr, timeout=None): - self._browser_backend.driver.switch_to_window(self._window_handle) - if timeout: - logging.warning('timeout is not supported') - self._browser_backend.driver.execute_script(expr) - - def EvaluateJavaScript(self, expr, timeout=None): - self._browser_backend.driver.switch_to_window(self._window_handle) - if timeout: - logging.warning('timeout is not supported') - return self._browser_backend.driver.execute_script( - 'return eval(\'%s\')' % expr.replace('\'', '\\\'').replace('\n', ' ')) - - @property - def timeline_model(self): - # IE/Firefox has no timeline. - raise NotImplementedError() - - def StartTimelineRecording(self): - raise NotImplementedError() - - def StopTimelineRecording(self): - raise NotImplementedError() - - def ClearCache(self): - # Can't find a way to clear cache of a tab in IE/Firefox. - raise NotImplementedError() diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py deleted file mode 100644 index ea9c8346c4b..00000000000 --- a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2013 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 telemetry.core.backends.webdriver import webdriver_tab_backend - -class WebDriverTabListBackend(object): - def __init__(self, browser_backend): - self._browser_backend = browser_backend - # Stores the window handles. - self._tab_list = [] - - def Init(self): - self._UpdateTabList() - - def New(self, timeout=None): - # Webdriver API doesn't support tab controlling. - raise NotImplementedError() - - def __iter__(self): - self._UpdateTabList() - return self._tab_list.__iter__() - - def __len__(self): - self._UpdateTabList() - return len(self._tab_list) - - def __getitem__(self, index): - self._UpdateTabList() - if len(self._tab_list) <= index: - raise IndexError('list index out of range') - return self._tab_list[index] - - def _UpdateTabList(self): - window_handles = self._browser_backend.driver.window_handles - old_tab_list = self._tab_list - self._tab_list = [] - for window_handle in window_handles: - tab = None - for old_tab in old_tab_list: - if old_tab.window_handle == window_handle: - tab = old_tab - break - else: - tab = webdriver_tab_backend.WebDriverTabBackend( - self._browser_backend, window_handle) - self._tab_list.append(tab) diff --git a/chromium/tools/telemetry/telemetry/core/browser_finder.py b/chromium/tools/telemetry/telemetry/core/browser_finder.py index 0248857fb53..e316e05a84a 100644 --- a/chromium/tools/telemetry/telemetry/core/browser_finder.py +++ b/chromium/tools/telemetry/telemetry/core/browser_finder.py @@ -5,7 +5,6 @@ import logging -from telemetry.core.backends.webdriver import webdriver_desktop_browser_finder from telemetry.core.chrome import android_browser_finder from telemetry.core.chrome import cros_browser_finder from telemetry.core.chrome import desktop_browser_finder @@ -13,8 +12,7 @@ from telemetry.core.chrome import desktop_browser_finder BROWSER_FINDERS = [ desktop_browser_finder, android_browser_finder, - cros_browser_finder, - webdriver_desktop_browser_finder, + cros_browser_finder ] ALL_BROWSER_TYPES = ','.join([bf.ALL_BROWSER_TYPES for bf in BROWSER_FINDERS]) diff --git a/chromium/tools/telemetry/telemetry/core/browser_options.py b/chromium/tools/telemetry/telemetry/core/browser_options.py index 70d3c1ff340..69f304823a1 100644 --- a/chromium/tools/telemetry/telemetry/core/browser_options.py +++ b/chromium/tools/telemetry/telemetry/core/browser_options.py @@ -54,7 +54,6 @@ class BrowserOptions(optparse.Values): self.repeat_options = repeat_options.RepeatOptions() self.output_file = None - self.skip_navigate_on_repeat = False def Copy(self): return copy.deepcopy(self) diff --git a/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py index d3a7bdcfc2e..86a942fa2ff 100644 --- a/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py +++ b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py @@ -101,17 +101,6 @@ def CanFindAvailableBrowsers(logging=real_logging): adb_works = True else: adb_works = False - if adb_works and sys.platform.startswith('linux'): - # Workaround for crbug.com/268450 - import psutil - adb_commands.GetAttachedDevices() - pids = [p.pid for p in psutil.process_iter() if 'adb' in p.name] - with open(os.devnull, 'w') as devnull: - for pid in pids: - subprocess.check_call(['taskset', '-p', '0x1', str(pid)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=devnull) return adb_works diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py index 805a48147c5..0f73add3119 100644 --- a/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py +++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py @@ -106,7 +106,7 @@ class CrOSBrowserBackend(chrome_browser_backend.ChromeBrowserBackend): def _GetSessionManagerPid(self, procs): """Returns the pid of the session_manager process, given the list of processes.""" - for pid, process, _, _ in procs: + for pid, process, _ in procs: if process.startswith('/sbin/session_manager '): return pid return None @@ -129,7 +129,7 @@ class CrOSBrowserBackend(chrome_browser_backend.ChromeBrowserBackend): return None # Find the chrome process that is the child of the session_manager. - for pid, process, ppid, _ in procs: + for pid, process, ppid in procs: if ppid != session_manager_pid: continue for path in self.CHROME_PATHS: diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py index 6f1f16084eb..a825e5b290a 100644 --- a/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py +++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py @@ -245,19 +245,19 @@ class CrOSInterface(object): return res def ListProcesses(self): - """Returns (pid, cmd, ppid, state) of all processes on the device.""" + """Returns a tuple (pid, cmd, ppid) of all processes on the device.""" stdout, stderr = self.RunCmdOnDevice([ '/bin/ps', '--no-headers', '-A', - '-o', 'pid,ppid,args,state'], quiet=True) + '-o', 'pid,ppid,args'], quiet=True) assert stderr == '', stderr procs = [] for l in stdout.split('\n'): # pylint: disable=E1103 if l == '': continue - m = re.match('^\s*(\d+)\s+(\d+)\s+(.+)\s+(.+)', l, re.DOTALL) + m = re.match('^\s*(\d+)\s+(\d+)\s+(.+)', l, re.DOTALL) assert m - procs.append((int(m.group(1)), m.group(3), int(m.group(2)), m.group(4))) + procs.append((int(m.group(1)), m.group(3), int(m.group(2)))) logging.debug("ListProcesses(<predicate>)->[%i processes]" % len(procs)) return procs @@ -267,7 +267,7 @@ class CrOSInterface(object): def KillAllMatching(self, predicate): kills = ['kill', '-KILL'] - for pid, cmd, _, _ in self.ListProcesses(): + for pid, cmd, _ in self.ListProcesses(): if predicate(cmd): logging.info('Killing %s, pid %d' % cmd, pid) kills.append(pid) diff --git a/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py index 93f33d8c677..8ef4d6d1bcc 100644 --- a/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py +++ b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py @@ -150,13 +150,10 @@ def FindAllAvailableBrowsers(options): else: raise Exception('Platform not recognized') - def IsExecutable(path): - return os.path.isfile(path) and os.access(path, os.X_OK) - # Add the explicit browser executable if given. if options.browser_executable: normalized_executable = os.path.expanduser(options.browser_executable) - if IsExecutable(normalized_executable): + if os.path.exists(normalized_executable): browser_directory = os.path.dirname(options.browser_executable) browsers.append(PossibleDesktopBrowser('exact', options, normalized_executable, flash_path, @@ -168,7 +165,7 @@ def FindAllAvailableBrowsers(options): def AddIfFound(browser_type, build_dir, type_dir, app_name, content_shell): browser_directory = os.path.join(chrome_root, build_dir, type_dir) app = os.path.join(browser_directory, app_name) - if IsExecutable(app): + if os.path.exists(app): browsers.append(PossibleDesktopBrowser(browser_type, options, app, flash_path, content_shell, browser_directory, @@ -189,12 +186,12 @@ def FindAllAvailableBrowsers(options): mac_canary = mac_canary_root + 'Contents/MacOS/Google Chrome Canary' mac_system_root = '/Applications/Google Chrome.app' mac_system = mac_system_root + '/Contents/MacOS/Google Chrome' - if IsExecutable(mac_canary): + if os.path.exists(mac_canary): browsers.append(PossibleDesktopBrowser('canary', options, mac_canary, None, False, mac_canary_root)) - if IsExecutable(mac_system): + if os.path.exists(mac_system): browsers.append(PossibleDesktopBrowser('system', options, mac_system, None, False, mac_system_root)) @@ -226,7 +223,7 @@ def FindAllAvailableBrowsers(options): def AddIfFoundWin(browser_name, app_path): browser_directory = os.path.join(path, app_path) app = os.path.join(browser_directory, chromium_app_name) - if IsExecutable(app): + if os.path.exists(app): browsers.append(PossibleDesktopBrowser(browser_name, options, app, flash_path, False, browser_directory)) diff --git a/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py index 02f6a71b89d..3c0a25c7069 100644 --- a/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py +++ b/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py @@ -53,18 +53,6 @@ class CrosPlatformBackend(platform_backend.PlatformBackend): def GetOSName(self): return 'chromeos' - def GetChildPids(self, pid): - """Returns a list of child pids of |pid|.""" - all_process_info = self._cri.ListProcesses() - processes = [] - for pid, _, ppid, state in all_process_info: - processes.append((pid, ppid, state)) - return proc_util.GetChildPids(processes, pid) - - def GetCommandLine(self, pid): - command = self._GetPsOutput(['command'], pid) - return command[0] if command else None - def CanFlushIndividualFilesFromSystemCache(self): return True diff --git a/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py index fa20b54b930..e3c60ace394 100644 --- a/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py +++ b/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py @@ -4,8 +4,9 @@ import subprocess +from collections import defaultdict + from telemetry.core.platform import desktop_platform_backend -from telemetry.core.platform import proc_util class PosixPlatformBackend(desktop_platform_backend.DesktopPlatformBackend): @@ -37,11 +38,23 @@ class PosixPlatformBackend(desktop_platform_backend.DesktopPlatformBackend): def GetChildPids(self, pid): """Returns a list of child pids of |pid|.""" - ps_output = self._GetPsOutput(['pid', 'ppid', 'state']) - processes = [] - for pid_ppid_state in ps_output: - processes.append(pid_ppid_state.split()) - return proc_util.GetChildPids(processes, pid) + pid_ppid_state_list = self._GetPsOutput(['pid', 'ppid', 'state']) + + child_dict = defaultdict(list) + for pid_ppid_state in pid_ppid_state_list: + curr_pid, curr_ppid, state = pid_ppid_state.split() + if 'Z' in state: + continue # Ignore zombie processes + child_dict[int(curr_ppid)].append(int(curr_pid)) + queue = [pid] + child_ids = [] + while queue: + parent = queue.pop() + if parent in child_dict: + children = child_dict[parent] + queue.extend(children) + child_ids.extend(children) + return child_ids def GetCommandLine(self, pid): command = self._GetPsOutput(['command'], pid) diff --git a/chromium/tools/telemetry/telemetry/core/platform/proc_util.py b/chromium/tools/telemetry/telemetry/core/platform/proc_util.py index 656eb846996..9be108f946b 100644 --- a/chromium/tools/telemetry/telemetry/core/platform/proc_util.py +++ b/chromium/tools/telemetry/telemetry/core/platform/proc_util.py @@ -2,8 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from collections import defaultdict - try: import resource # pylint: disable=F0401 except ImportError: @@ -13,7 +11,6 @@ except ImportError: def _ConvertKbToByte(value): return int(value.replace('kB','')) * 1024 - def _GetProcFileDict(contents): retval = {} for line in contents.splitlines(): @@ -21,7 +18,6 @@ def _GetProcFileDict(contents): retval[key.strip()] = value.strip() return retval - def GetSystemCommitCharge(meminfo_contents): meminfo = _GetProcFileDict(meminfo_contents) return (_ConvertKbToByte(meminfo['MemTotal']) @@ -29,7 +25,6 @@ def GetSystemCommitCharge(meminfo_contents): - _ConvertKbToByte(meminfo['Buffers']) - _ConvertKbToByte(meminfo['Cached'])) - def GetMemoryStats(status_contents, stats): status = _GetProcFileDict(status_contents) if not status or not stats or 'Z' in status['State']: @@ -39,27 +34,9 @@ def GetMemoryStats(status_contents, stats): 'WorkingSetSize': int(stats[23]) * resource.getpagesize(), 'WorkingSetSizePeak': _ConvertKbToByte(status['VmHWM'])} - def GetIOStats(io_contents): io = _GetProcFileDict(io_contents) return {'ReadOperationCount': int(io['syscr']), 'WriteOperationCount': int(io['syscw']), 'ReadTransferCount': int(io['rchar']), 'WriteTransferCount': int(io['wchar'])} - - -def GetChildPids(processes, pid): - child_dict = defaultdict(list) - for curr_pid, curr_ppid, state in processes: - if 'Z' in state: - continue # Ignore zombie processes - child_dict[int(curr_ppid)].append(int(curr_pid)) - queue = [pid] - child_ids = [] - while queue: - parent = queue.pop() - if parent in child_dict: - children = child_dict[parent] - queue.extend(children) - child_ids.extend(children) - return child_ids diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py deleted file mode 100644 index 186a8d0025d..00000000000 --- a/chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py +++ /dev/null @@ -1,251 +0,0 @@ -# Copyright 2013 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 re -import signal -import subprocess -import sys -import tempfile - -from telemetry.core.platform import profiler - - -# Parses one line of strace output, for example: -# 6052 1311456063.159722 read(8, "\1\0\0\0\0\0\0\0", 8) = 8 <0.000022> -_STRACE_LINE_RE = re.compile( - '^(?P<tid>\d+)\s+' - '(?P<ts>\d+)' - '(?P<micro>.\d+)\s+' - '(?P<func>.*?)' - '[(](?P<args>.*?)[)]\s+=\s+' - '(?P<ret>.*?)\s+' - '<(?P<dur>[\d.]+)>$') - -_UNFINISHED_LINE_RE = re.compile( - '^(?P<tid>\d+)\s+' - '(?P<line>.*?)' - '<unfinished ...>$') - -_RESUMED_LINE_RE = re.compile( - '^(?P<tid>\d+)\s+' - '(?P<ts>\d+)' - '(?P<micro>.\d+)\s+' - '<[.][.][.]\s(?P<func>.*?)\sresumed>' - '(?P<line>.*?)$') - -_KILLED_LINE_RE = re.compile( - '^(?P<tid>\d+)\s+' - '(?P<ts>\d+)' - '(?P<micro>.\d+)\s+' - '[+][+][+] killed by SIGKILL [+][+][+]$') - - -def _StraceToChromeTrace(pid, infile): - """Returns chrometrace json format for |infile| strace output.""" - # Map of fd:file_name for open file descriptors. Useful for displaying - # file name instead of the descriptor number. - fd_map = {} - - # Map of tid:interrupted_call for the interrupted call on each thread. It is - # possible to context switch during a system call. In this case we must - # match up the lines. - interrupted_call_map = {} - - out = [] - with open(infile, 'r') as f: - for line in f.readlines(): - # Ignore kill lines for now. - m = _KILLED_LINE_RE.match(line) - if m: - continue - - # If this line is interrupted, then remember it and continue. - m = _UNFINISHED_LINE_RE.match(line) - if m: - assert m.group('tid') not in interrupted_call_map - interrupted_call_map[m.group('tid')] = line - continue - - # If this is a resume of a previous line, stitch it together. - interrupted = False - m = _RESUMED_LINE_RE.match(line) - if m: - interrupted = True - assert m.group('tid') in interrupted_call_map - line = interrupted_call_map[m.group('tid')].replace( - '<unfinished ...>', m.group('line')) - del interrupted_call_map[m.group('tid')] - - # At this point we can do a normal match. - m = _STRACE_LINE_RE.match(line) - if not m: - if ('exit' not in line and - 'Profiling timer expired' not in line and - '<unavailable>' not in line): - logging.warn('Failed to parse line: %s' % line) - continue - - ts_begin = int(1000000 * (int(m.group('ts')) + float(m.group('micro')))) - ts_end = ts_begin + int(1000000 * float(m.group('dur'))) - tid = int(m.group('tid')) - function_name = unicode(m.group('func'), errors='ignore') - function_args = unicode(m.group('args'), errors='ignore') - ret = unicode(m.group('ret'), errors='ignore') - cat = 'strace' - - possible_fd_arg = None - first_arg = function_args.split(',')[0] - if first_arg and first_arg.strip().isdigit(): - possible_fd_arg = first_arg.strip() - - if function_name == 'open' and ret.isdigit(): - # 1918 1311606151.649379 open("/foo/bar.so", O_RDONLY) = 7 <0.000088> - fd_map[ret] = first_arg - - args = { - 'args': function_args, - 'ret': ret, - } - if interrupted: - args['interrupted'] = True - if possible_fd_arg and possible_fd_arg in fd_map: - args['fd%s' % first_arg] = fd_map[possible_fd_arg] - - out.append({ - 'cat': cat, - 'pid': pid, - 'tid': tid, - 'ts': ts_begin, - 'ph': 'B', # Begin - 'name': function_name, - }) - out.append({ - 'cat': cat, - 'pid': pid, - 'tid': tid, - 'ts': ts_end, - 'ph': 'E', # End - 'name': function_name, - 'args': args, - }) - - return out - - -def _GenerateTraceMetadata(model): - out = [] - for process in model.processes: - out.append({ - 'name': 'process_name', - 'ph': 'M', # Metadata - 'pid': process, - 'args': { - 'name': model.processes[process].name - } - }) - for thread in model.processes[process].threads: - out.append({ - 'name': 'thread_name', - 'ph': 'M', # Metadata - 'pid': process, - 'tid': thread, - 'args': { - 'name': model.processes[process].threads[thread].name - } - }) - return out - - -class _SingleProcessStraceProfiler(object): - """An internal class for using perf for a given process.""" - def __init__(self, pid, output_file, platform_backend): - self._pid = pid - self._platform_backend = platform_backend - self._output_file = output_file - self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0) - self._proc = subprocess.Popen( - ['strace', '-ttt', '-f', '-T', '-p', str(pid), '-o', output_file], - stdout=self._tmp_output_file, stderr=subprocess.STDOUT) - - def CollectProfile(self): - if ('renderer' in self._output_file and - not self._platform_backend.GetCommandLine(self._pid)): - logging.warning('Renderer was swapped out during profiling. ' - 'To collect a full profile rerun with ' - '"--extra-browser-args=--single-process"') - self._proc.send_signal(signal.SIGINT) - exit_code = self._proc.wait() - try: - if exit_code: - raise Exception('strace failed with exit code %d. Output:\n%s' % ( - exit_code, self._GetStdOut())) - finally: - self._tmp_output_file.close() - - return _StraceToChromeTrace(self._pid, self._output_file) - - def _GetStdOut(self): - self._tmp_output_file.flush() - try: - with open(self._tmp_output_file.name) as f: - return f.read() - except IOError: - return '' - - -class StraceProfiler(profiler.Profiler): - - def __init__(self, browser_backend, platform_backend, output_path): - super(StraceProfiler, self).__init__( - browser_backend, platform_backend, output_path) - assert self._browser_backend.supports_tracing - self._browser_backend.StartTracing(None, 10) - process_output_file_map = self._GetProcessOutputFileMap() - self._process_profilers = [] - self._output_file = output_path + '.json' - for pid, output_file in process_output_file_map.iteritems(): - if 'zygote' in output_file: - continue - self._process_profilers.append( - _SingleProcessStraceProfiler(pid, output_file, platform_backend)) - - @classmethod - def name(cls): - return 'strace' - - @classmethod - def is_supported(cls, options): - if sys.platform != 'linux2': - return False - # TODO(tonyg): This should be supported on android and cros. - if options and (options.browser_type.startswith('android') - or options.browser_type.startswith('cros')): - return False - return True - - @classmethod - def CustomizeBrowserOptions(cls, options): - options.AppendExtraBrowserArg('--no-sandbox') - options.AppendExtraBrowserArg('--allow-sandbox-debugging') - - def CollectProfile(self): - print 'Processing trace...' - - out_json = [] - - for single_process in self._process_profilers: - out_json.extend(single_process.CollectProfile()) - - self._browser_backend.StopTracing() - model = self._browser_backend.GetTraceResultAndReset().AsTimelineModel() - out_json.extend(_GenerateTraceMetadata(model)) - - with open(self._output_file, 'w') as f: - f.write(json.dumps(out_json, separators=(',', ':'))) - - print 'Trace saved as %s' % self._output_file - print 'To view, open in chrome://tracing' - return [self._output_file] diff --git a/chromium/tools/telemetry/telemetry/page/actions/wait.py b/chromium/tools/telemetry/telemetry/page/actions/wait.py index 39f061ae149..bfe0b27e6fd 100644 --- a/chromium/tools/telemetry/telemetry/page/actions/wait.py +++ b/chromium/tools/telemetry/telemetry/page/actions/wait.py @@ -1,8 +1,6 @@ # Copyright (c) 2012 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 re import time from telemetry.core import util @@ -45,14 +43,14 @@ class WaitAction(page_action.PageAction): elif self.condition == 'element': assert hasattr(self, 'text') or hasattr(self, 'selector') - if hasattr(self, 'text'): + if self.text: callback_code = 'function(element) { return element != null; }' util.WaitFor( lambda: util.FindElementAndPerformAction( tab, self.text, callback_code), self.DEFAULT_TIMEOUT) - else: + elif self.selector: util.WaitFor(lambda: tab.EvaluateJavaScript( - 'document.querySelector("%s") != null' % re.escape(self.selector)), + 'document.querySelector("%s") != null' % self.selector), self.DEFAULT_TIMEOUT) elif self.condition == 'javascript': diff --git a/chromium/tools/telemetry/telemetry/page/cloud_storage.py b/chromium/tools/telemetry/telemetry/page/cloud_storage.py index 5d537c822ac..d52c62252e1 100644 --- a/chromium/tools/telemetry/telemetry/page/cloud_storage.py +++ b/chromium/tools/telemetry/telemetry/page/cloud_storage.py @@ -27,14 +27,6 @@ class CloudStorageError(Exception): pass -class CredentialsError(CloudStorageError): - def __init__(self, gsutil_path): - super(CredentialsError, self).__init__( - 'Attempted to download a file from Cloud Storage but you have no ' - 'configured credentials. Run "%s config" to configure your ' - 'credentials. The project-id field can be left blank.' % gsutil_path) - - def _DownloadGsutil(): logging.info('Downloading gsutil') response = urllib2.urlopen(_GSUTIL_URL) @@ -72,10 +64,7 @@ def _RunCommand(args): stdout, stderr = gsutil.communicate() if gsutil.returncode: - if ('You are attempting to access protected data with ' - 'no configured credentials.' in stderr): - raise CredentialsError(gsutil_path) - raise CloudStorageError(stderr) + raise CloudStorageError(stderr.splitlines()[-1]) return stdout diff --git a/chromium/tools/telemetry/telemetry/page/page_runner.py b/chromium/tools/telemetry/telemetry/page/page_runner.py index 89ab3115de7..1df51dec457 100644 --- a/chromium/tools/telemetry/telemetry/page/page_runner.py +++ b/chromium/tools/telemetry/telemetry/page/page_runner.py @@ -32,7 +32,6 @@ class _RunState(object): self._first_browser = True self.first_page = collections.defaultdict(lambda: True) self.profiler_dir = None - self.repeat_state = None def StartBrowser(self, test, page_set, page, possible_browser, credentials_path, archive_path): @@ -111,9 +110,12 @@ class PageState(object): def PreparePage(self, page, tab, test=None): if page.is_file: - serving_dirs = page.serving_dirs_and_file[0] + serving_dirs, filename = page.serving_dirs_and_file if tab.browser.SetHTTPServerDirectories(serving_dirs) and test: test.DidStartHTTPServer(tab) + target_side_url = tab.browser.http_server.UrlOf(filename) + else: + target_side_url = page.url if page.credentials: if not tab.browser.credentials.LoginNeeded(tab, page.credentials): @@ -123,19 +125,6 @@ class PageState(object): if test: if test.clear_cache_before_each_run: tab.ClearCache() - - def ImplicitPageNavigation(self, page, tab, test=None): - """Executes the implicit navigation that occurs for every page iteration. - - This function will be called once per page before any actions are executed. - """ - if page.is_file: - filename = page.serving_dirs_and_file[1] - target_side_url = tab.browser.http_server.UrlOf(filename) - else: - target_side_url = page.url - - if test: test.WillNavigateToPage(page, tab) tab.Navigate(target_side_url, page.script_to_evaluate_on_commit) if test: @@ -192,7 +181,7 @@ def _PrepareAndRunPage(test, page_set, expectations, options, page, state.browser.platform, page) try: - _RunPage(test, page, state, expectation, + _RunPage(test, page, state.tab, expectation, results_for_current_run, options) _CheckThermalThrottling(state.browser.platform) except exceptions.TabCrashException: @@ -273,19 +262,19 @@ def Run(test, page_set, expectations, options): try: test.WillRunTest(state.tab) - state.repeat_state = page_runner_repeat.PageRunnerRepeatState( - options.repeat_options) + repeat_state = page_runner_repeat.PageRunnerRepeatState( + options.repeat_options) - state.repeat_state.WillRunPageSet() - while state.repeat_state.ShouldRepeatPageSet(): + repeat_state.WillRunPageSet() + while repeat_state.ShouldRepeatPageSet(): for page in pages: - state.repeat_state.WillRunPage() - while state.repeat_state.ShouldRepeatPage(): + repeat_state.WillRunPage() + while repeat_state.ShouldRepeatPage(): # execute test on page _PrepareAndRunPage(test, page_set, expectations, options, page, credentials_path, possible_browser, results, state) - state.repeat_state.DidRunPage() - state.repeat_state.DidRunPageSet() + repeat_state.DidRunPage() + repeat_state.DidRunPageSet() test.DidRunTest(state.tab, results) finally: @@ -367,24 +356,13 @@ def _CheckArchives(page_set, pages, results): pages_missing_archive_path + pages_missing_archive_data] -def _RunPage(test, page, state, expectation, results, options): +def _RunPage(test, page, tab, expectation, results, options): logging.info('Running %s' % page.url) page_state = PageState() - tab = state.tab - - def ProcessError(): - logging.error('%s:\n%s', page.url, traceback.format_exc()) - if expectation == 'fail': - logging.info('Error was expected\n') - results.AddSuccess(page) - else: - results.AddError(page, sys.exc_info()) try: page_state.PreparePage(page, tab, test) - if state.repeat_state.ShouldNavigate(options.skip_navigate_on_repeat): - page_state.ImplicitPageNavigation(page, tab, test) test.Run(options, page, tab, results) util.CloseConnections(tab) except page_test.Failure: @@ -396,9 +374,11 @@ def _RunPage(test, page, state, expectation, results, options): results.AddFailure(page, sys.exc_info()) except (util.TimeoutException, exceptions.LoginException, exceptions.ProfilingException): - ProcessError() + logging.error('%s:\n%s', page.url, traceback.format_exc()) + results.AddError(page, sys.exc_info()) except (exceptions.TabCrashException, exceptions.BrowserGoneException): - ProcessError() + logging.error('%s:\n%s', page.url, traceback.format_exc()) + results.AddError(page, sys.exc_info()) # Run() catches these exceptions to relaunch the tab/browser, so re-raise. raise except Exception: diff --git a/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py b/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py index 5c80f5c68fd..acec0b0b714 100644 --- a/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py +++ b/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py @@ -52,10 +52,3 @@ class PageRunnerRepeatState(object): self.page_iters >= self.options.page_repeat_iters): return False return True - - def ShouldNavigate(self, skip_navigate_on_repeat): - """Returns whether we are navigating to pages on page repeats. - - Always navigate on the first iteration of a page and on every new pageset. - """ - return self.page_iters == 0 or not skip_navigate_on_repeat
\ No newline at end of file diff --git a/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py b/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py index 815683b56c6..2ff1cfc9f02 100644 --- a/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py +++ b/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py @@ -59,27 +59,8 @@ class PageRunnerTests(unittest.TestCase): options.output_format = 'none' results = page_runner.Run(Test('RunTest'), ps, expectations, options) self.assertEquals(0, len(results.successes)) - self.assertEquals(0, len(results.failures)) self.assertEquals(1, len(results.errors)) - def testHandlingOfCrashedTabWithExpectedFailure(self): - ps = page_set.PageSet() - expectations = test_expectations.TestExpectations() - expectations.Fail('chrome://crash') - page1 = page_module.Page('chrome://crash', ps) - ps.pages.append(page1) - - class Test(page_test.PageTest): - def RunTest(self, *args): - pass - - options = options_for_unittests.GetCopy() - options.output_format = 'none' - results = page_runner.Run(Test('RunTest'), ps, expectations, options) - self.assertEquals(1, len(results.successes)) - self.assertEquals(0, len(results.failures)) - self.assertEquals(0, len(results.errors)) - def testDiscardFirstResult(self): ps = page_set.PageSet() expectations = test_expectations.TestExpectations() diff --git a/chromium/tools/telemetry/telemetry/page/test_expectations.py b/chromium/tools/telemetry/telemetry/page/test_expectations.py index 2ed9faa30a0..45689223878 100644 --- a/chromium/tools/telemetry/telemetry/page/test_expectations.py +++ b/chromium/tools/telemetry/telemetry/page/test_expectations.py @@ -6,7 +6,7 @@ import fnmatch OS_MODIFIERS = ['win', 'xp', 'vista', 'win7', 'mac', 'leopard', 'snowleopard', 'lion', 'mountainlion', - 'linux', 'chromeos', 'android'] + 'linux', 'chromeos'] GPU_MODIFIERS = ['nvidia', 'amd', 'intel'] CONFIG_MODIFIERS = ['debug', 'release'] diff --git a/chromium/tools/telemetry/telemetry/unittest/system_stub.py b/chromium/tools/telemetry/telemetry/unittest/system_stub.py index b647f5fb593..42078444e74 100644 --- a/chromium/tools/telemetry/telemetry/unittest/system_stub.py +++ b/chromium/tools/telemetry/telemetry/unittest/system_stub.py @@ -88,9 +88,6 @@ class OsModuleStub(object): def exists(self, path): return path in self.files - def isfile(self, path): - return path in self.files - def join(self, *paths): def IsAbsolutePath(path): if self.sys.platform.startswith('win'): @@ -118,8 +115,6 @@ class OsModuleStub(object): def dirname(self, filename): # pylint: disable=R0201 return os.path.dirname(filename) - X_OK = os.X_OK - def __init__(self, sys_module=real_sys): self.path = OsModuleStub.OsPathModuleStub(sys_module) self.display = ':0' @@ -128,9 +123,6 @@ class OsModuleStub(object): self.program_files_x86 = None self.devnull = os.devnull - def access(self, path, _): - return path in self.path.files - def getenv(self, name): if name == 'DISPLAY': return self.display |