Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: chrome/test/webdriver/chromedriver_launcher.py

Issue 7331004: Move chromedriver tests to test subdirectory. Add script to run all chromedriver (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: ... Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/webdriver/WEBDRIVER_TESTS ('k') | chrome/test/webdriver/chromedriver_paths.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Launches and kills ChromeDriver.
7
8 For ChromeDriver documentation, refer to:
9 http://dev.chromium.org/developers/testing/webdriver-for-chrome
10 """
11
12 import logging
13 import os
14 import platform
15 import signal
16 import subprocess
17 import sys
18 import threading
19 import urllib2
20
21
22 class ChromeDriverLauncher:
23 """Launches and kills the ChromeDriver process."""
24
25 def __init__(self, exe_path=None, root_path=None, port=None, url_base=None):
26 """Initializes a new launcher.
27
28 Args:
29 exe_path: path to the ChromeDriver executable
30 root_path: base path from which ChromeDriver webserver will serve files
31 port: port that ChromeDriver will listen on
32 url_base: base URL which ChromeDriver webserver will listen from
33 """
34 self._exe_path = exe_path
35 self._root_path = root_path
36 self._port = port
37 self._url_base = url_base
38 if self._exe_path is None:
39 self._exe_path = ChromeDriverLauncher.LocateExe()
40 if self._exe_path is None:
41 raise RuntimeError('ChromeDriver exe could not be found in its default '
42 'location. Searched in following directories: ' +
43 ', '.join(self.DefaultExeLocations()))
44 if self._root_path is not None:
45 self._root_path = os.path.abspath(self._root_path)
46 self._process = None
47
48 if not os.path.exists(self._exe_path):
49 raise RuntimeError('ChromeDriver exe not found at: ' + self._exe_path)
50
51 os.environ['PATH'] = os.path.dirname(self._exe_path) + os.environ['PATH']
52 self.Start()
53
54 @staticmethod
55 def DefaultExeLocations():
56 """Returns the paths that are used to find the ChromeDriver executable.
57
58 Returns:
59 a list of directories that would be searched for the executable
60 """
61 script_dir = os.path.dirname(__file__)
62 chrome_src = os.path.abspath(os.path.join(
63 script_dir, os.pardir, os.pardir, os.pardir))
64 bin_dirs = {
65 'linux2': [ os.path.join(chrome_src, 'out', 'Debug'),
66 os.path.join(chrome_src, 'sconsbuild', 'Debug'),
67 os.path.join(chrome_src, 'out', 'Release'),
68 os.path.join(chrome_src, 'sconsbuild', 'Release')],
69 'linux3': [ os.path.join(chrome_src, 'out', 'Debug'),
70 os.path.join(chrome_src, 'sconsbuild', 'Debug'),
71 os.path.join(chrome_src, 'out', 'Release'),
72 os.path.join(chrome_src, 'sconsbuild', 'Release')],
73 'darwin': [ os.path.join(chrome_src, 'xcodebuild', 'Debug'),
74 os.path.join(chrome_src, 'xcodebuild', 'Release')],
75 'win32': [ os.path.join(chrome_src, 'chrome', 'Debug'),
76 os.path.join(chrome_src, 'build', 'Debug'),
77 os.path.join(chrome_src, 'chrome', 'Release'),
78 os.path.join(chrome_src, 'build', 'Release')],
79 }
80 return [os.getcwd()] + bin_dirs.get(sys.platform, [])
81
82 @staticmethod
83 def LocateExe():
84 """Attempts to locate the ChromeDriver executable.
85
86 This searches the current directory, then checks the appropriate build
87 locations according to platform.
88
89 Returns:
90 absolute path to the ChromeDriver executable, or None if not found
91 """
92 exe_name = 'chromedriver'
93 if platform.system() == 'Windows':
94 exe_name += '.exe'
95
96 for dir in ChromeDriverLauncher.DefaultExeLocations():
97 path = os.path.join(dir, exe_name)
98 if os.path.exists(path):
99 return os.path.abspath(path)
100 return None
101
102 def Start(self):
103 """Starts a new ChromeDriver process.
104
105 Kills a previous one if it is still running.
106
107 Raises:
108 RuntimeError if ChromeDriver does not start
109 """
110 def _WaitForLaunchResult(stdout, started_event, launch_result):
111 """Reads from the stdout of ChromeDriver and parses the launch result.
112
113 Args:
114 stdout: handle to ChromeDriver's standard output
115 started_event: condition variable to notify when the launch result
116 has been parsed
117 launch_result: dictionary to add the result of this launch to
118 """
119 status_line = stdout.readline()
120 started_event.acquire()
121 try:
122 launch_result['success'] = status_line.startswith('Started')
123 launch_result['status_line'] = status_line
124 if launch_result['success']:
125 port_line = stdout.readline()
126 launch_result['port'] = int(port_line.split('=')[1])
127 started_event.notify()
128 finally:
129 started_event.release()
130
131 if self._process is not None:
132 self.Kill()
133
134 chromedriver_args = [self._exe_path]
135 if self._root_path is not None:
136 chromedriver_args += ['--root=%s' % self._root_path]
137 if self._port is not None:
138 chromedriver_args += ['--port=%d' % self._port]
139 if self._url_base is not None:
140 chromedriver_args += ['--url-base=%s' % self._url_base]
141 proc = subprocess.Popen(chromedriver_args,
142 stdout=subprocess.PIPE)
143 if proc is None:
144 raise RuntimeError('ChromeDriver cannot be started')
145 self._process = proc
146
147 # Wait for ChromeDriver to be initialized before returning.
148 launch_result = {}
149 started_event = threading.Condition()
150 started_event.acquire()
151 spawn_thread = threading.Thread(
152 target=_WaitForLaunchResult,
153 args=(proc.stdout, started_event, launch_result))
154 spawn_thread.start()
155 started_event.wait(20)
156 timed_out = 'success' not in launch_result
157 started_event.release()
158 if timed_out:
159 raise RuntimeError('ChromeDriver did not respond')
160 elif not launch_result['success']:
161 raise RuntimeError('ChromeDriver failed to launch: ' +
162 launch_result['status_line'])
163 self._port = launch_result['port']
164 logging.info('ChromeDriver running on port %s' % self._port)
165
166 def Kill(self):
167 """Kills a currently running ChromeDriver process, if it is running."""
168 def _WaitForShutdown(process, shutdown_event):
169 """Waits for the process to quit and then notifies."""
170 process.wait()
171 shutdown_event.acquire()
172 shutdown_event.notify()
173 shutdown_event.release()
174
175 if self._process is None:
176 return
177 try:
178 urllib2.urlopen(self.GetURL() + '/shutdown').close()
179 except urllib2.URLError:
180 # Could not shutdown. Kill.
181 pid = self._process.pid
182 if platform.system() == 'Windows':
183 subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)])
184 else:
185 os.kill(pid, signal.SIGTERM)
186
187 # Wait for ChromeDriver process to exit before returning.
188 # Even if we had to kill the process above, we still should call wait
189 # to cleanup the zombie.
190 shutdown_event = threading.Condition()
191 shutdown_event.acquire()
192 wait_thread = threading.Thread(
193 target=_WaitForShutdown,
194 args=(self._process, shutdown_event))
195 wait_thread.start()
196 shutdown_event.wait(10)
197 shutdown_event.release()
198 self._process = None
199
200 def GetURL(self):
201 url = 'http://localhost:' + str(self._port)
202 if self._url_base:
203 url += self._url_base
204 return url
205
206 def GetPort(self):
207 return self._port
OLDNEW
« no previous file with comments | « chrome/test/webdriver/WEBDRIVER_TESTS ('k') | chrome/test/webdriver/chromedriver_paths.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698