diff --git a/testing/performance/talos/README.txt b/testing/performance/talos/README.txt index 71f649e80f8f..83602a7160bd 100755 --- a/testing/performance/talos/README.txt +++ b/testing/performance/talos/README.txt @@ -9,19 +9,28 @@ these performance tests: Make sure to correctly set the path to python in the paths.py file. - After you download and install Python 2.4, you'll need to install + After you download and install Python 2.4, Windows users will need to install some extensions: * Python Win32 Extensions These extensions provide some support for process management and performance monitoring. http://prdownloads.sourceforge.net/pywin32/pywin32-208.win32-py2.4.exe?download + + Mac users may use Python 2.3.5, included with Mac OS X, but they will need + to download the 'subprocess.py' file included with more recent Python distributions + and install it in the library path (/Library/Python/2.3/site-packages/). * Apache HTTP Server Found at http://httpd.apache.org/ The page cycler works on a local Apache server. After installing Apache simply place the page_load_test/ directory into htdocs/ directory of Apache (found on most systems at c:\Program Files\Apache Software Foundation\Apache2.2\htdocs) + + * Syck YAML Parser + You'll need to download and install Syck from http://whytheluckystiff.net/syck/ + Install the binary (a standard install) and the Python extension: + cd ext/python/ && python setup.py build && sudo python setup.py install 1. Make sure the prerequisites, above, are installed. 2. Copy this entire directory and all subdirectories onto your local disk @@ -32,41 +41,8 @@ these performance tests: network.proxy.http_port:80 - these settings ensure that the browser will only contact local web pages and will not attempt to pull information from the live web, this is important for collecting consistant testing results. - It should look something like this: - -# Filename will be appended to the timestamp in the report filename. -# Use letters and underscores only -filename: testfilename - -# The title of the report -title: testtitle - -# Name of profile to test -Test profile 1: - # Path to Firefox to test - firefox: C:\cygwin\tmp\test\firefox\firefox\firefox.exe - - branch: testbranch - - branchid: testbranchid - - profile_path: C:\win32\base_profile - - # Preferences to set in the test (use "preferences : {}" for no prefs) - preferences : - browser.shell.checkDefaultBrowser : false - dom.allow_scripts_to_close_windows : true - dom.disable_open_during_load: false - browser.dom.window.dump.enabled: true - network.proxy.type : 1 - network.proxy.http : localhost - network.proxy.http_port : 80 - - # Extensions to install in test (use "extensions: {}" for none) - extensions : - # Need quotes around guid because of curly braces - "{12345678-1234-1234-1234-abcd12345678}" : c:\path\to\unzipped\xpi - foo@sample.com : c:\path\to\other\unzipped\xpi + Your config file should look something like the sample.config file in the + Talos distribution. 5. Provide a pages/ directory The page_load_test/ relies upon having a pages directory that includes the web pages diff --git a/testing/performance/talos/base_profile/prefs.js b/testing/performance/talos/base_profile/prefs.js new file mode 100755 index 000000000000..86dc607298c9 --- /dev/null +++ b/testing/performance/talos/base_profile/prefs.js @@ -0,0 +1,8 @@ +// This file is needed to work around a Firefox bug where capability.principal +// prefs in user.js don't get recognized until the second browser launch +// which is too late for our purposes of using quit.js. Loading the principals +// from prefs.js avoids this issue. +user_pref("capability.principal.codebase.p0.granted", "UniversalPreferencesWrite UniversalXPConnect UniversalPreferencesRead"); +user_pref("capability.principal.codebase.p0.id", "file://"); +user_pref("capability.principal.codebase.p0.subjectName", ""); +user_pref("signed.applets.codebase_principal_support", true); diff --git a/testing/performance/talos/config.py b/testing/performance/talos/config.py index b57dde9db07a..ac404e6d111c 100644 --- a/testing/performance/talos/config.py +++ b/testing/performance/talos/config.py @@ -41,7 +41,6 @@ __author__ = 'annie.sullivan@gmail.com (Annie Sullivan)' - BROWSER_HEIGHT = 768 BROWSER_WIDTH = 1024 @@ -85,12 +84,14 @@ TP_RESOLUTION = 1 """Run page load test. For possible values of counters argument on Windows, see http://technet2.microsoft.com/WindowsServer/en/Library/86b5d116-6fb3-427b-af8c-9077162125fe1033.mspx?mfr=true - Possible values on Linux: + Possible values on Linux and Mac: 'Private Bytes', '% Processor Time', 'RSS' """ - COUNTERS = ['Private Bytes', 'Working Set', '% Processor Time'] """URL for the results server""" RESULTS_SERVER = 'graphserver.url.here' RESULTS_LINK = '/bulk.cgi' + +"""Enable/disable debugging output""" +DEBUG = 0 diff --git a/testing/performance/talos/ffprocess.py b/testing/performance/talos/ffprocess.py index a701aa75ae5c..b1802bf1d573 100755 --- a/testing/performance/talos/ffprocess.py +++ b/testing/performance/talos/ffprocess.py @@ -45,6 +45,7 @@ import platform import os import re import time +import subprocess import config @@ -52,6 +53,8 @@ if platform.system() == "Linux": from ffprocess_linux import * elif platform.system() == "Windows": from ffprocess_win32 import * +elif platform.system() == "Darwin": + from ffprocess_mac import * @@ -61,7 +64,7 @@ def SyncAndSleep(): """ os.spawnl(os.P_WAIT, config.SYNC) - time.sleep(3) + time.sleep(5) def RunProcessAndWaitForOutput(command, process_name, output_regex, timeout): @@ -83,7 +86,8 @@ def RunProcessAndWaitForOutput(command, process_name, output_regex, timeout): """ # Start the process - handle = os.popen(command) + process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True, shell=True, env=os.environ) + handle = process.stdout # Wait for it to print output, terminate, or time out. time_elapsed = 0 @@ -96,7 +100,7 @@ def RunProcessAndWaitForOutput(command, process_name, output_regex, timeout): (bytes, current_output) = NonBlockingReadProcessOutput(handle) output += current_output - + result = output_regex.search(output) if result: try: diff --git a/testing/performance/talos/ffprocess_mac.py b/testing/performance/talos/ffprocess_mac.py new file mode 100644 index 000000000000..8f8dc30ac66f --- /dev/null +++ b/testing/performance/talos/ffprocess_mac.py @@ -0,0 +1,164 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is standalone Firefox Mac performance test. +# +# The Initial Developer of the Original Code is Google Inc. +# Portions created by the Initial Developer are Copyright (C) 2006 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Annie Sullivan (original author) +# Ben Hearsum (OS independence) +# Zach Lipton (Mac port) +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +import subprocess +import signal +import os +import time +import config +from select import select + + +def GenerateFirefoxCommandLine(firefox_path, profile_dir, url): + """Generates the command line for a process to run Firefox + + Args: + firefox_path: String containing the path to the firefox binary to use + profile_dir: String containing the directory of the profile to run Firefox in + url: String containing url to start with. + """ + + profile_arg = '' + if profile_dir: + profile_arg = '-profile %s' % profile_dir + + url_arg = '' + if url: + url_arg = '-url %s' % url + + cmd = '%s %s %s -width %d -height %d' % (firefox_path, + profile_arg, + url_arg, + config.BROWSER_WIDTH, + config.BROWSER_HEIGHT) + return cmd + + +def GetPidsByName(process_name): + """Searches for processes containing a given string. + + Args: + process_name: The string to be searched for + + Returns: + A list of PIDs containing the string. An empty list is returned if none are + found. + """ + + matchingPids = [] + + command = ['ps -Axc'] + handle = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True, shell=True) + + # wait for the process to terminate + handle.wait() + data = handle.stdout.readlines() + + # find all matching processes and add them to the list + for line in data: + if line.find(process_name) >= 0: + # splits by whitespace, the first one should be the pid + pid = int(line.split()[0]) + matchingPids.append(pid) + + return matchingPids + + +def ProcessesWithNameExist(process_name): + """Returns true if there are any processes running with the + given name. Useful to check whether a Firefox process is still running + + Args: + process_name: String containing the process name, i.e. "firefox" + + Returns: + True if any processes with that name are running, False otherwise. + """ + + pids = GetPidsByName(process_name) + return len(pids) > 0 + + +def TerminateProcess(pid): + """Helper function to terminate a process, given the pid + + Args: + pid: integer process id of the process to terminate. + """ + os.kill(pid, signal.SIGTERM) + +def TerminateAllProcesses(process_name): + """Helper function to terminate all processes with the given process name + + Args: + process_name: String containing the process name, i.e. "firefox" + """ + pids = GetPidsByName(process_name) + for pid in pids: + TerminateProcess(pid) + +def NonBlockingReadProcessOutput(handle): + """Does a non-blocking read from the output of the process + with the given handle. + + Args: + handle: The process handle returned from os.popen() + + Returns: + A tuple (bytes, output) containing the number of output + bytes read, and the actual output. + """ + + output = "" + num_avail = 0 + + # check for data + # select() does not seem to work well with pipes. + # after data is available once it *always* thinks there is data available + # readline() will continue to return an empty string however + # so we can use this behavior to work around the problem + while select([handle], [], [], 0)[0]: + line = handle.readline() + if line: + output += line + else: + break + # this statement is true for encodings that have 1byte/char + num_avail = len(output) + + return (num_avail, output) diff --git a/testing/performance/talos/ffprofile.py b/testing/performance/talos/ffprofile.py index 190c0e6720ad..95b25acb8951 100755 --- a/testing/performance/talos/ffprofile.py +++ b/testing/performance/talos/ffprofile.py @@ -53,14 +53,16 @@ import shutil import tempfile import time +import utils import ffprocess import config if platform.system() == "Linux": - from ffprofile_linux import * + from ffprofile_unix import * elif platform.system() == "Windows": from ffprofile_win32 import * - +elif platform.system() == "Darwin": + from ffprofile_unix import * def PrefString(name, value, newline): """Helper function to create a pref string for Firefox profile prefs.js @@ -150,5 +152,6 @@ def InitializeNewProfile(firefox_path, profile_dir): time.sleep(5) if not ffprocess.ProcessesWithNameExist("firefox"): return - + utils.debug("terminating firefox process") ffprocess.TerminateAllProcesses("firefox") + ffprocess.SyncAndSleep() diff --git a/testing/performance/talos/ffprofile_linux.py b/testing/performance/talos/ffprofile_unix.py similarity index 97% rename from testing/performance/talos/ffprofile_linux.py rename to testing/performance/talos/ffprofile_unix.py index 1f6a266405af..7ef4e810aff7 100644 --- a/testing/performance/talos/ffprofile_linux.py +++ b/testing/performance/talos/ffprofile_unix.py @@ -20,6 +20,7 @@ # Contributor(s): # Annie Sullivan (original author) # Ben Hearsum (OS independence) +# Zach Lipton (Mac port) # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or diff --git a/testing/performance/talos/getInfo.html b/testing/performance/talos/getInfo.html index 50c4259e6c16..fcbf50b4807c 100644 --- a/testing/performance/talos/getInfo.html +++ b/testing/performance/talos/getInfo.html @@ -39,13 +39,15 @@ + shutdown script diff --git a/testing/performance/talos/initialize.html b/testing/performance/talos/initialize.html index 379aead7aa71..2d689a5bc623 100755 --- a/testing/performance/talos/initialize.html +++ b/testing/performance/talos/initialize.html @@ -38,10 +38,11 @@ + shutdown script - + This page should close Firefox. If it does not, please make sure that the dom.allow_scripts_to_close_windows preference is set to true in about:config diff --git a/testing/performance/talos/page_load_test/framecycler.html b/testing/performance/talos/page_load_test/framecycler.html index f09c9b3ee978..57e429094eda 100644 --- a/testing/performance/talos/page_load_test/framecycler.html +++ b/testing/performance/talos/page_load_test/framecycler.html @@ -1,10 +1,12 @@ +