On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / testing / performance / win32 / ffprocess.py
bloba4b0cef93155ead55a3343de9f2fa88f2992439c
1 #!c:/Python24/python.exe
3 # ***** BEGIN LICENSE BLOCK *****
4 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 # The contents of this file are subject to the Mozilla Public License Version
7 # 1.1 (the "License"); you may not use this file except in compliance with
8 # the License. You may obtain a copy of the License at
9 # http://www.mozilla.org/MPL/
11 # Software distributed under the License is distributed on an "AS IS" basis,
12 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 # for the specific language governing rights and limitations under the
14 # License.
16 # The Original Code is standalone Firefox Windows performance test.
18 # The Initial Developer of the Original Code is Google Inc.
19 # Portions created by the Initial Developer are Copyright (C) 2006
20 # the Initial Developer. All Rights Reserved.
22 # Contributor(s):
23 # Annie Sullivan <annie.sullivan@gmail.com> (original author)
25 # Alternatively, the contents of this file may be used under the terms of
26 # either the GNU General Public License Version 2 or later (the "GPL"), or
27 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 # in which case the provisions of the GPL or the LGPL are applicable instead
29 # of those above. If you wish to allow use of your version of this file only
30 # under the terms of either the GPL or the LGPL, and not to allow others to
31 # use your version of this file under the terms of the MPL, indicate your
32 # decision by deleting the provisions above and replace them with the notice
33 # and other provisions required by the GPL or the LGPL. If you do not delete
34 # the provisions above, a recipient may use your version of this file under
35 # the terms of any one of the MPL, the GPL or the LGPL.
37 # ***** END LICENSE BLOCK *****
39 """A set of functions for process management on Windows.
40 """
42 __author__ = 'annie.sullivan@gmail.com (Annie Sullivan)'
45 import msvcrt
46 import os
47 import re
48 import time
49 import win32api
50 import win32file
51 import win32pdhutil
52 import win32pipe
54 import paths
57 def GetCygwinPath(dos_path):
58 """Helper function to get the Cygwin path from a dos path.
59 Used to generate a Firefox command line piped through the
60 Cygwin bash shell
62 Args:
63 dos_path: String containing the dos path
65 Returns:
66 String containing the cygwin path
67 """
69 # Convert the path to a cygwin path. Assumes the path starts with
70 # /cygdrive/driveletter
71 cygwin_path = '/' + dos_path[3:] # Remove 'C:\'
72 cygwin_path = cygwin_path.replace('\\', '/') # Backslashes->slashes
73 cygwin_path = cygwin_path.replace(' ', '\\ ') # Escape spaces
74 cygwin_path = '/cygdrive/' + dos_path[0] + cygwin_path # Add drive letter
75 return cygwin_path
78 def GenerateFirefoxCommandLine(firefox_path, profile_dir, url):
79 """Generates the command line for a process to run Firefox, wrapped
80 by cygwin so that we can read the output from dump() statements.
82 Args:
83 firefox_path: String containing the path to the firefox exe to use
84 profile_dir: String containing the directory of the profile to run Firefox in
85 url: String containing url to start with.
86 """
88 profile_arg = ''
89 if profile_dir:
90 profile_dir = profile_dir.replace('\\', '\\\\\\')
91 profile_arg = '-profile %s' % profile_dir
93 url_arg = ''
94 if url:
95 url_arg = '-url %s' % url
97 cmd = '%s "%s %s %s"' % (paths.CYGWIN,
98 GetCygwinPath(firefox_path),
99 profile_arg,
100 url_arg)
101 return cmd
104 def SyncAndSleep():
105 """Runs sync and sleeps for a few seconds between Firefox runs.
106 Otherwise "Firefox is already running.." errors occur
109 os.spawnl(os.P_WAIT, paths.SYNC)
110 time.sleep(3)
113 def TerminateProcess(pid):
114 """Helper function to terminate a process, given the pid
116 Args:
117 pid: integer process id of the process to terminate.
120 PROCESS_TERMINATE = 1
121 handle = win32api.OpenProcess(PROCESS_TERMINATE, False, pid)
122 win32api.TerminateProcess(handle, -1)
123 win32api.CloseHandle(handle)
126 def ProcessesWithNameExist(process_name):
127 """Returns true if there are any processes running with the
128 given name. Useful to check whether a Firefox process is still running
130 Args:
131 process_name: String containing the process name, i.e. "firefox"
133 Returns:
134 True if any processes with that name are running, False otherwise.
137 try:
138 pids = win32pdhutil.FindPerformanceAttributesByName(process_name, counter="ID Process")
139 return len(pids) > 0
140 except:
141 # Might get an exception if there are no instances of the process running.
142 return False
145 def TerminateAllProcesses(process_name):
146 """Helper function to terminate all processes with the given process name
148 Args:
149 process_name: String containing the process name, i.e. "firefox"
152 # Get all the process ids of running instances of this process, and terminate them.
153 try:
154 pids = win32pdhutil.FindPerformanceAttributesByName(process_name, counter="ID Process")
155 for pid in pids:
156 TerminateProcess(pid)
157 except:
158 # Might get an exception if there are no instances of the process running.
159 pass
162 def NonBlockingReadProcessOutput(handle):
163 """Does a non-blocking read from the output of the process
164 with the given handle.
166 Args:
167 handle: The process handle returned from os.popen()
169 Returns:
170 A tuple (bytes, output) containing the number of output
171 bytes read, and the actual output.
174 output = ""
176 try:
177 osfhandle = msvcrt.get_osfhandle(handle.fileno())
178 (read, num_avail, num_message) = win32pipe.PeekNamedPipe(osfhandle, 0)
179 if num_avail > 0:
180 (error_code, output) = win32file.ReadFile(osfhandle, num_avail, None)
182 return (num_avail, output)
183 except:
184 return (0, output)
187 def RunProcessAndWaitForOutput(command, process_name, output_regex, timeout):
188 """Runs the given process and waits for the output that matches the given
189 regular expression. Stops if the process exits early or times out.
191 Args:
192 command: String containing command to run
193 process_name: Name of the process to run, in case it has to be killed
194 output_regex: Regular expression to check against each output line.
195 If the output matches, the process is terminated and
196 the function returns.
197 timeout: Time to wait before terminating the process and returning
199 Returns:
200 A tuple (match, timedout) where match is the match of the regular
201 expression, and timed out is true if the process timed out and
202 false otherwise.
205 # Start the process
206 handle = os.popen(command)
208 # Wait for it to print output, terminate, or time out.
209 time_elapsed = 0
210 output = ''
211 interval = 2 # Wait 2 seconds in between checks
213 while time_elapsed < timeout:
214 time.sleep(interval)
215 time_elapsed += interval
217 (bytes, current_output) = NonBlockingReadProcessOutput(handle)
218 output += current_output
220 result = output_regex.search(output)
221 if result:
222 try:
223 return_val = result.group(1)
224 TerminateAllProcesses(process_name)
225 return (return_val, False)
226 except IndexError:
227 # Didn't really match
228 pass
230 # Timed out.
231 TerminateAllProcesses(process_name)
232 return (None, True)